diff options
author | Clyybber <darkmine956@gmail.com> | 2020-09-22 18:24:13 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-22 18:24:13 +0200 |
commit | 4b9eea2fcc5d030393ca9020fbbee33fcb48d41a (patch) | |
tree | 4024e3074ebbaf636ee0f00415f9f0861c4bf522 /compiler | |
parent | 11c377c1149a23657a7f0dd897866cb550ade8d1 (diff) | |
download | Nim-4b9eea2fcc5d030393ca9020fbbee33fcb48d41a.tar.gz |
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
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/lookups.nim | 12 | ||||
-rw-r--r-- | compiler/procfind.nim | 12 | ||||
-rw-r--r-- | compiler/semstmts.nim | 9 | ||||
-rw-r--r-- | compiler/semtempl.nim | 4 |
4 files changed, 24 insertions, 13 deletions
diff --git a/compiler/lookups.nim b/compiler/lookups.nim index c0db25950..744f77cf8 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -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): diff --git a/compiler/procfind.nim b/compiler/procfind.nim index 1d897758a..0bdb3dae6 100644 --- a/compiler/procfind.nim +++ b/compiler/procfind.nim @@ -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 diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index e99ce8937..53d381f5d 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -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: diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index a1afd2c6d..1ec8c07b0 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -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) |