Templates will pick the candidate in the nearest scope when symbols are mixed-in
This commit is contained in:
parent
754e2ef1db
commit
8f3d5a25a6
6 changed files with 32 additions and 16 deletions
|
|
@ -1430,6 +1430,10 @@ proc skipGenericOwner*(s: PSym): PSym =
|
||||||
result = if sfFromGeneric in s.flags: s.owner.owner
|
result = if sfFromGeneric in s.flags: s.owner.owner
|
||||||
else: s.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.} =
|
proc isRoutine*(s: PSym): bool {.inline.} =
|
||||||
result = s.kind in {skProc, skTemplate, skMacro, skIterator, skMethod,
|
result = s.kind in {skProc, skTemplate, skMacro, skIterator, skMethod,
|
||||||
skConverter}
|
skConverter}
|
||||||
|
|
|
||||||
|
|
@ -1164,7 +1164,7 @@ proc semAsgn(c: PContext, n: PNode): PNode =
|
||||||
if lhsIsResult: {efAllowDestructor} else: {})
|
if lhsIsResult: {efAllowDestructor} else: {})
|
||||||
if lhsIsResult:
|
if lhsIsResult:
|
||||||
n.typ = enforceVoidContext
|
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:
|
if cmpTypes(c, lhs.typ, rhs.typ) == isGeneric:
|
||||||
internalAssert c.p.resultSym != nil
|
internalAssert c.p.resultSym != nil
|
||||||
lhs.typ = rhs.typ
|
lhs.typ = rhs.typ
|
||||||
|
|
|
||||||
|
|
@ -421,6 +421,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
s = semIdentVis(c, skTemplate, n.sons[0], {})
|
s = semIdentVis(c, skTemplate, n.sons[0], {})
|
||||||
# check parameter list:
|
# check parameter list:
|
||||||
|
s.scope = c.currentScope
|
||||||
pushOwner(s)
|
pushOwner(s)
|
||||||
openScope(c)
|
openScope(c)
|
||||||
n.sons[namePos] = newSymNode(s, n.sons[namePos].info)
|
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:
|
elif result.kind == tyGenericParam and not cl.allowMetaTypes:
|
||||||
internalError(cl.info, "substitution with generic parameter")
|
internalError(cl.info, "substitution with generic parameter")
|
||||||
|
|
||||||
proc instCopyType(t: PType): PType =
|
proc instCopyType(cl: var TReplTypeVars, t: PType): PType =
|
||||||
result = copyType(t, t.owner, false)
|
# XXX: relying on allowMetaTypes is a kludge
|
||||||
|
result = copyType(t, t.owner, cl.allowMetaTypes)
|
||||||
result.flags.incl tfFromGeneric
|
result.flags.incl tfFromGeneric
|
||||||
result.flags.excl tfInstClearedFlags
|
result.flags.excl tfInstClearedFlags
|
||||||
|
|
||||||
|
|
@ -184,7 +185,7 @@ proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType =
|
||||||
if x.kind == tyGenericParam:
|
if x.kind == tyGenericParam:
|
||||||
x = lookupTypeVar(cl, x)
|
x = lookupTypeVar(cl, x)
|
||||||
if x != nil:
|
if x != nil:
|
||||||
if header == nil: header = instCopyType(t)
|
if header == nil: header = instCopyType(cl, t)
|
||||||
header.sons[i] = x
|
header.sons[i] = x
|
||||||
propagateToOwner(header, x)
|
propagateToOwner(header, x)
|
||||||
|
|
||||||
|
|
@ -193,7 +194,7 @@ proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType =
|
||||||
result = searchInstTypes(header)
|
result = searchInstTypes(header)
|
||||||
if result != nil: return
|
if result != nil: return
|
||||||
else:
|
else:
|
||||||
header = instCopyType(t)
|
header = instCopyType(cl, t)
|
||||||
|
|
||||||
result = newType(tyGenericInst, t.sons[0].owner)
|
result = newType(tyGenericInst, t.sons[0].owner)
|
||||||
# be careful not to propagate unnecessary flags here (don't use rawAddSon)
|
# be careful not to propagate unnecessary flags here (don't use rawAddSon)
|
||||||
|
|
@ -295,7 +296,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||||
result = lookup
|
result = lookup
|
||||||
if tfUnresolved in t.flags: result = result.base
|
if tfUnresolved in t.flags: result = result.base
|
||||||
of tyGenericInst:
|
of tyGenericInst:
|
||||||
result = instCopyType(t)
|
result = instCopyType(cl, t)
|
||||||
for i in 1 .. <result.sonsLen:
|
for i in 1 .. <result.sonsLen:
|
||||||
result.sons[i] = ReplaceTypeVarsT(cl, result.sons[i])
|
result.sons[i] = ReplaceTypeVarsT(cl, result.sons[i])
|
||||||
propagateToOwner(result, result.lastSon)
|
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)
|
t.sons[0] = makeRangeType(cl.c, 0, value.intVal - 1, value.info)
|
||||||
|
|
||||||
if containsGenericType(t):
|
if containsGenericType(t):
|
||||||
result = instCopyType(t)
|
result = instCopyType(cl, t)
|
||||||
result.size = -1 # needs to be recomputed
|
result.size = -1 # needs to be recomputed
|
||||||
|
|
||||||
for i in countup(0, sonsLen(result) - 1):
|
for i in countup(0, sonsLen(result) - 1):
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,8 @@ type
|
||||||
state*: TCandidateState
|
state*: TCandidateState
|
||||||
callee*: PType # may not be nil!
|
callee*: PType # may not be nil!
|
||||||
calleeSym*: PSym # may 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
|
call*: PNode # modified call
|
||||||
bindings*: TIdTable # maps types to types
|
bindings*: TIdTable # maps types to types
|
||||||
baseTypeMatch: bool # needed for conversions from T to openarray[T]
|
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) =
|
binding: PNode, calleeScope = -1) =
|
||||||
initCandidateAux(ctx, c, callee.typ)
|
initCandidateAux(ctx, c, callee.typ)
|
||||||
c.calleeSym = callee
|
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)
|
initIdTable(c.bindings)
|
||||||
c.errors = nil
|
c.errors = nil
|
||||||
if binding != nil and callee.kind in routineKinds:
|
if binding != nil and callee.kind in routineKinds:
|
||||||
|
|
@ -166,9 +175,8 @@ proc cmpCandidates*(a, b: TCandidate): int =
|
||||||
if result != 0: return
|
if result != 0: return
|
||||||
result = a.convMatches - b.convMatches
|
result = a.convMatches - b.convMatches
|
||||||
if result != 0: return
|
if result != 0: return
|
||||||
if (a.calleeScope != -1) and (b.calleeScope != -1):
|
result = a.calleeScope - b.calleeScope
|
||||||
result = a.calleeScope - b.calleeScope
|
if result != 0: return
|
||||||
if result != 0: return
|
|
||||||
# the other way round because of other semantics:
|
# the other way round because of other semantics:
|
||||||
result = b.inheritancePenalty - a.inheritancePenalty
|
result = b.inheritancePenalty - a.inheritancePenalty
|
||||||
if result != 0: return
|
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)
|
if a.kind == tyTuple: result = recordRel(c, f, a)
|
||||||
of tyObject:
|
of tyObject:
|
||||||
if a.kind == tyObject:
|
if a.kind == tyObject:
|
||||||
if sameObjectTypes(f, a): result = isEqual
|
if sameObjectTypes(f, a):
|
||||||
elif tfHasMeta in f.flags: result = recordRel(c, f, a)
|
result = isEqual
|
||||||
|
# elif tfHasMeta in f.flags: result = recordRel(c, f, a)
|
||||||
else:
|
else:
|
||||||
var depth = isObjectSubtype(a, f)
|
var depth = isObjectSubtype(a, f)
|
||||||
if depth > 0:
|
if depth > 0:
|
||||||
|
|
|
||||||
|
|
@ -875,6 +875,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
||||||
tyArray, tyProc, tyConst, tyMutable, tyVarargs, tyIter,
|
tyArray, tyProc, tyConst, tyMutable, tyVarargs, tyIter,
|
||||||
tyOrdinal, tyTypeClasses:
|
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)
|
result = sameChildrenAux(a, b, c) and sameFlags(a, b)
|
||||||
if result and a.kind == tyProc:
|
if result and a.kind == tyProc:
|
||||||
result = ((IgnoreCC in c.flags) or a.callConv == b.callConv) and
|
result = ((IgnoreCC in c.flags) or a.callConv == b.callConv) and
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue