diff options
author | Zahary Karadjov <zahary@gmail.com> | 2013-12-31 03:58:31 +0200 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2013-12-31 04:04:59 +0200 |
commit | 8f3d5a25a692f1630bb24fbaf4951e68c9c99e28 (patch) | |
tree | 39750ca34ebdc95c26ad337c1b08599ee0550e91 /compiler | |
parent | 754e2ef1db61610cba1b96752fa37c6e923e2808 (diff) | |
download | Nim-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.nim | 4 | ||||
-rw-r--r-- | compiler/semexprs.nim | 2 | ||||
-rw-r--r-- | compiler/semtempl.nim | 1 | ||||
-rw-r--r-- | compiler/semtypinst.nim | 15 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 23 | ||||
-rw-r--r-- | compiler/types.nim | 3 |
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 |