mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-18 21:40:32 +00:00
Templates will pick the candidate in the nearest scope when symbols are mixed-in
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user