summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2013-12-31 03:58:31 +0200
committerZahary Karadjov <zahary@gmail.com>2013-12-31 04:04:59 +0200
commit8f3d5a25a692f1630bb24fbaf4951e68c9c99e28 (patch)
tree39750ca34ebdc95c26ad337c1b08599ee0550e91 /compiler
parent754e2ef1db61610cba1b96752fa37c6e923e2808 (diff)
downloadNim-8f3d5a25a692f1630bb24fbaf4951e68c9c99e28.tar.gz
Templates will pick the candidate in the nearest scope when symbols are mixed-in
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ast.nim4
-rw-r--r--compiler/semexprs.nim2
-rw-r--r--compiler/semtempl.nim1
-rw-r--r--compiler/semtypinst.nim15
-rw-r--r--compiler/sigmatch.nim23
-rw-r--r--compiler/types.nim3
6 files changed, 32 insertions, 16 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 8699d1715..e25f10a66 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -1430,6 +1430,10 @@ proc skipGenericOwner*(s: PSym): PSym =
   result = if sfFromGeneric in s.flags: s.owner.owner
            else: s.owner
 
+proc originatingModule*(s: PSym): PSym =
+  result = s.owner
+  while result.kind != skModule: result = result.owner
+
 proc isRoutine*(s: PSym): bool {.inline.} =
   result = s.kind in {skProc, skTemplate, skMacro, skIterator, skMethod,
                       skConverter}
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 14f611c5c..00c0e0f78 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -1164,7 +1164,7 @@ proc semAsgn(c: PContext, n: PNode): PNode =
         if lhsIsResult: {efAllowDestructor} else: {})
     if lhsIsResult:
       n.typ = enforceVoidContext
-      if lhs.sym.typ.isMetaType:
+      if lhs.sym.typ.isMetaType and lhs.sym.typ.kind != tyTypeDesc:
         if cmpTypes(c, lhs.typ, rhs.typ) == isGeneric:
           internalAssert c.p.resultSym != nil
           lhs.typ = rhs.typ
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index da38f8625..569d92d33 100644
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -421,6 +421,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
   else:
     s = semIdentVis(c, skTemplate, n.sons[0], {})
   # check parameter list:
+  s.scope = c.currentScope
   pushOwner(s)
   openScope(c)
   n.sons[namePos] = newSymNode(s, n.sons[namePos].info)
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index fb7be3a38..ec56f75e4 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -162,8 +162,9 @@ proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType =
   elif result.kind == tyGenericParam and not cl.allowMetaTypes:
     internalError(cl.info, "substitution with generic parameter")
 
-proc instCopyType(t: PType): PType =
-  result = copyType(t, t.owner, false)
+proc instCopyType(cl: var TReplTypeVars, t: PType): PType =
+  # XXX: relying on allowMetaTypes is a kludge
+  result = copyType(t, t.owner, cl.allowMetaTypes)
   result.flags.incl tfFromGeneric
   result.flags.excl tfInstClearedFlags
 
@@ -184,7 +185,7 @@ proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType =
     if x.kind == tyGenericParam:
       x = lookupTypeVar(cl, x)
       if x != nil:
-        if header == nil: header = instCopyType(t)
+        if header == nil: header = instCopyType(cl, t)
         header.sons[i] = x
         propagateToOwner(header, x)
   
@@ -193,7 +194,7 @@ proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType =
     result = searchInstTypes(header)
     if result != nil: return
   else:
-    header = instCopyType(t)
+    header = instCopyType(cl, t)
   
   result = newType(tyGenericInst, t.sons[0].owner)
   # be careful not to propagate unnecessary flags here (don't use rawAddSon)
@@ -279,7 +280,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
   if t.kind in {tyStatic, tyGenericParam} + tyTypeClasses:
     let lookup = PType(idTableGet(cl.typeMap, t))
     if lookup != nil: return lookup
-
+ 
   case t.kind
   of tyGenericInvokation:
     result = handleGenericInvokation(cl, t)
@@ -295,7 +296,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
       result = lookup
       if tfUnresolved in t.flags: result = result.base
   of tyGenericInst:
-    result = instCopyType(t)
+    result = instCopyType(cl, t)
     for i in 1 .. <result.sonsLen:
       result.sons[i] = ReplaceTypeVarsT(cl, result.sons[i])
     propagateToOwner(result, result.lastSon)
@@ -308,7 +309,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
         t.sons[0] = makeRangeType(cl.c, 0, value.intVal - 1, value.info)
     
     if containsGenericType(t):
-      result = instCopyType(t)
+      result = instCopyType(cl, t)
       result.size = -1 # needs to be recomputed
       
       for i in countup(0, sonsLen(result) - 1):
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 9a00a308b..96975c917 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -31,7 +31,8 @@ type
     state*: TCandidateState
     callee*: PType           # may not be nil!
     calleeSym*: PSym         # may be nil
-    calleeScope: int         # may be -1 for unknown scope
+    calleeScope*: int        # scope depth:
+                             # is this a top-level symbol or a nested proc?
     call*: PNode             # modified call
     bindings*: TIdTable      # maps types to types
     baseTypeMatch: bool      # needed for conversions from T to openarray[T]
@@ -86,7 +87,15 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
                     binding: PNode, calleeScope = -1) =
   initCandidateAux(ctx, c, callee.typ)
   c.calleeSym = callee
-  c.calleeScope = calleeScope
+  if callee.kind in skProcKinds and calleeScope == -1:
+    if callee.originatingModule == ctx.module:
+      let rootSym = if sfFromGeneric notin callee.flags: callee
+                    else: callee.owner
+      c.calleeScope = rootSym.scope.depthLevel
+    else:
+      c.calleeScope = 1
+  else:
+    c.calleeScope = calleeScope
   initIdTable(c.bindings)
   c.errors = nil
   if binding != nil and callee.kind in routineKinds:
@@ -166,9 +175,8 @@ proc cmpCandidates*(a, b: TCandidate): int =
   if result != 0: return
   result = a.convMatches - b.convMatches
   if result != 0: return
-  if (a.calleeScope != -1) and (b.calleeScope != -1):
-    result = a.calleeScope - b.calleeScope
-    if result != 0: return
+  result = a.calleeScope - b.calleeScope
+  if result != 0: return
   # the other way round because of other semantics:
   result = b.inheritancePenalty - a.inheritancePenalty
   if result != 0: return
@@ -566,8 +574,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
     if a.kind == tyTuple: result = recordRel(c, f, a)
   of tyObject:
     if a.kind == tyObject:
-      if sameObjectTypes(f, a): result = isEqual
-      elif tfHasMeta in f.flags: result = recordRel(c, f, a)
+      if sameObjectTypes(f, a):
+        result = isEqual
+        # elif tfHasMeta in f.flags: result = recordRel(c, f, a)
       else:
         var depth = isObjectSubtype(a, f)
         if depth > 0:
diff --git a/compiler/types.nim b/compiler/types.nim
index 1bf18fbe2..68e816c13 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -874,7 +874,8 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
      tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr,
      tyArray, tyProc, tyConst, tyMutable, tyVarargs, tyIter,
      tyOrdinal, tyTypeClasses:
-    cycleCheck()    
+    cycleCheck()
+    if a.kind == tyTypeClass and a.n != nil: return a.n == b.n
     result = sameChildrenAux(a, b, c) and sameFlags(a, b)
     if result and a.kind == tyProc:
       result = ((IgnoreCC in c.flags) or a.callConv == b.callConv) and