mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-09 05:14:20 +00:00
Fix forward declarations in shadow scope contexts (#15386)
* Fix forward declarations in shadow scope contexts * Add testcase for #15385 * Less empty lines * Fix tests * Inline isShadowScope * Add original testcase (with reduced amount of iterations) * Add testcase without forward decl
This commit is contained in:
@@ -91,13 +91,15 @@ proc skipAlias*(s: PSym; n: PNode; conf: ConfigRef): PSym =
|
||||
message(conf, n.info, warnDeprecated, "use " & result.name.s & " instead; " &
|
||||
s.name.s & " is deprecated")
|
||||
|
||||
proc isShadowScope*(s: PScope): bool {.inline.} = s.parent != nil and s.parent.depthLevel == s.depthLevel
|
||||
|
||||
proc localSearchInScope*(c: PContext, s: PIdent): PSym =
|
||||
result = strTableGet(c.currentScope.symbols, s)
|
||||
var shadow = c.currentScope
|
||||
while result == nil and shadow.parent != nil and shadow.depthLevel == shadow.parent.depthLevel:
|
||||
var scope = c.currentScope
|
||||
result = strTableGet(scope.symbols, s)
|
||||
while result == nil and scope.isShadowScope:
|
||||
# We are in a shadow scope, check in the parent too
|
||||
result = strTableGet(shadow.parent.symbols, s)
|
||||
shadow = shadow.parent
|
||||
scope = scope.parent
|
||||
result = strTableGet(scope.symbols, s)
|
||||
|
||||
proc searchInScopes*(c: PContext, s: PIdent): PSym =
|
||||
for scope in walkScopes(c.currentScope):
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
# This is needed for proper handling of forward declarations.
|
||||
|
||||
import
|
||||
ast, astalgo, msgs, semdata, types, trees, strutils
|
||||
ast, astalgo, msgs, semdata, types, trees, strutils, lookups
|
||||
|
||||
proc equalGenericParams(procA, procB: PNode): bool =
|
||||
if procA.len != procB.len: return false
|
||||
@@ -28,7 +28,7 @@ proc equalGenericParams(procA, procB: PNode): bool =
|
||||
if not exprStructuralEquivalent(a.ast, b.ast): return
|
||||
result = true
|
||||
|
||||
proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
|
||||
proc searchForProcAux(c: PContext, scope: PScope, fn: PSym): PSym =
|
||||
const flags = {ExactGenericParams, ExactTypeDescValues,
|
||||
ExactConstraints, IgnoreCC}
|
||||
var it: TIdentIter
|
||||
@@ -50,6 +50,14 @@ proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
|
||||
discard
|
||||
result = nextIdentIter(it, scope.symbols)
|
||||
|
||||
proc searchForProc*(c: PContext, scope: PScope, fn: PSym): tuple[proto: PSym, comesFromShadowScope: bool] =
|
||||
var scope = scope
|
||||
result.proto = searchForProcAux(c, scope, fn)
|
||||
while result.proto == nil and scope.isShadowScope:
|
||||
scope = scope.parent
|
||||
result.proto = searchForProcAux(c, scope, fn)
|
||||
result.comesFromShadowScope = true
|
||||
|
||||
when false:
|
||||
proc paramsFitBorrow(child, parent: PNode): bool =
|
||||
result = false
|
||||
|
||||
@@ -1898,8 +1898,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
elif s.kind == skFunc:
|
||||
incl(s.flags, sfNoSideEffect)
|
||||
incl(s.typ.flags, tfNoSideEffect)
|
||||
var proto: PSym = if isAnon: nil
|
||||
else: searchForProc(c, oldScope, s)
|
||||
var (proto, comesFromShadowScope) = if isAnon: (nil, false)
|
||||
else: searchForProc(c, oldScope, s)
|
||||
if proto == nil and sfForward in s.flags:
|
||||
#This is a definition that shares its sym with its forward declaration (generated by a macro),
|
||||
#if the symbol is also gensymmed we won't find it with searchForProc, so we check here
|
||||
@@ -1941,8 +1941,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
onDefResolveForward(n[namePos].info, proto)
|
||||
if sfForward notin proto.flags and proto.magic == mNone:
|
||||
wrongRedefinition(c, n.info, proto.name.s, proto.info)
|
||||
excl(proto.flags, sfForward)
|
||||
incl(proto.flags, sfWasForwarded)
|
||||
if not comesFromShadowScope:
|
||||
excl(proto.flags, sfForward)
|
||||
incl(proto.flags, sfWasForwarded)
|
||||
closeScope(c) # close scope with wrong parameter symbols
|
||||
openScope(c) # open scope for old (correct) parameter symbols
|
||||
if proto.ast[genericParamsPos].kind != nkEmpty:
|
||||
|
||||
@@ -662,10 +662,10 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||
localError(c.config, n[bodyPos].info, errImplOfXNotAllowed % s.name.s)
|
||||
elif n[bodyPos].kind == nkEmpty:
|
||||
localError(c.config, n.info, "implementation of '$1' expected" % s.name.s)
|
||||
var proto = searchForProc(c, c.currentScope, s)
|
||||
var (proto, comesFromShadowscope) = searchForProc(c, c.currentScope, s)
|
||||
if proto == nil:
|
||||
addInterfaceOverloadableSymAt(c, c.currentScope, s)
|
||||
else:
|
||||
elif not comesFromShadowscope:
|
||||
symTabReplace(c.currentScope.symbols, proto, s)
|
||||
if n[patternPos].kind != nkEmpty:
|
||||
c.patterns.add(s)
|
||||
|
||||
Reference in New Issue
Block a user