diff options
author | Clyybber <darkmine956@gmail.com> | 2020-08-27 15:50:59 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-27 15:50:59 +0200 |
commit | fb58066b61b14f4a1d6cdb0f4a8f0a9ea4174d82 (patch) | |
tree | c6e573d9ac221c786ac9e0ca2cf0f186d87a6bbe /compiler | |
parent | d11933ad998fb0a3eb51bbefbaa53e583aaa3ac1 (diff) | |
download | Nim-fb58066b61b14f4a1d6cdb0f4a8f0a9ea4174d82.tar.gz |
Fix #5691 (#15158)
* Fix #5691 * Cleanup and thoughts * Use scope approach * Seperate defined/declared/declaredInScope magics * Fix declaredInScope * Update spec accordingly
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ast.nim | 2 | ||||
-rw-r--r-- | compiler/condsyms.nim | 1 | ||||
-rw-r--r-- | compiler/lookups.nim | 22 | ||||
-rw-r--r-- | compiler/sem.nim | 13 | ||||
-rw-r--r-- | compiler/semcall.nim | 4 | ||||
-rw-r--r-- | compiler/semexprs.nim | 42 | ||||
-rw-r--r-- | compiler/semgnrc.nim | 2 | ||||
-rw-r--r-- | compiler/semstmts.nim | 2 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 26 |
9 files changed, 65 insertions, 49 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 62c1e3894..06ff92e9f 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -617,7 +617,7 @@ var type TMagic* = enum # symbols that require compiler magic: mNone, - mDefined, mDefinedInScope, mCompiles, mArrGet, mArrPut, mAsgn, + mDefined, mDeclared, mDeclaredInScope, mCompiles, mArrGet, mArrPut, mAsgn, mLow, mHigh, mSizeOf, mAlignOf, mOffsetOf, mTypeTrait, mIs, mOf, mAddr, mType, mTypeOf, mPlugin, mEcho, mShallowCopy, mSlurp, mStaticExec, mStatic, diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index b7f7100f1..ad13f3e1e 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -119,3 +119,4 @@ proc initDefines*(symbols: StringTableRef) = defineSymbol("nimHasStacktraceMsgs") defineSymbol("nimDoesntTrackDefects") defineSymbol("nimHasLentIterators") + defineSymbol("nimHasDeclaredMagic") diff --git a/compiler/lookups.nim b/compiler/lookups.nim index a3a2bf49c..c0db25950 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -93,6 +93,11 @@ proc skipAlias*(s: PSym; n: PNode; conf: ConfigRef): PSym = 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: + # We are in a shadow scope, check in the parent too + result = strTableGet(shadow.parent.symbols, s) + shadow = shadow.parent proc searchInScopes*(c: PContext, s: PIdent): PSym = for scope in walkScopes(c.currentScope): @@ -231,6 +236,23 @@ proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) = addOverloadableSymAt(c, scope, sym) addInterfaceDeclAux(c, sym) +proc openShadowScope*(c: PContext) = + c.currentScope = PScope(parent: c.currentScope, + symbols: newStrTable(), + depthLevel: c.scopeDepth) + +proc closeShadowScope*(c: PContext) = + c.closeScope + +proc mergeShadowScope*(c: PContext) = + let shadowScope = c.currentScope + c.rawCloseScope + for sym in shadowScope.symbols: + if sym.kind in OverloadableSyms: + c.addInterfaceOverloadableSymAt(c.currentScope, sym) + else: + c.addInterfaceDecl(sym) + when defined(nimfix): # when we cannot find the identifier, retry with a changed identifier: proc altSpelling(x: PIdent): PIdent = diff --git a/compiler/sem.nim b/compiler/sem.nim index a07f62ca0..07c76eed4 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -383,12 +383,10 @@ when not defined(nimHasSinkInference): include hlo, seminst, semcall -when false: - # hopefully not required: - proc resetSemFlag(n: PNode) = - excl n.flags, nfSem - for i in 0..<n.safeLen: - resetSemFlag(n[i]) +proc resetSemFlag(n: PNode) = + excl n.flags, nfSem + for i in 0..<n.safeLen: + resetSemFlag(n[i]) proc semAfterMacroCall(c: PContext, call, macroResult: PNode, s: PSym, flags: TExprFlags): PNode = @@ -403,8 +401,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode, c.friendModules.add(s.owner.getModule) idSynchronizationPoint(5000) result = macroResult - excl(result.flags, nfSem) - #resetSemFlag n + resetSemFlag result if s.typ[0] == nil: result = semStmt(c, result, flags) else: diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 0c30ce45e..1a6f754ee 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -94,10 +94,6 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode, if c.currentScope.symbols.counter == counterInitial or syms.len != 0: matches(c, n, orig, z) if z.state == csMatch: - #if sym.name.s == "==" and (n.info ?? "temp3"): - # echo typeToString(sym.typ) - # writeMatches(z) - # little hack so that iterators are preferred over everything else: if sym.kind == skIterator: inc(z.exactMatches, 200) case best.state diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index cdd0f61dd..03da0aef0 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1854,29 +1854,32 @@ proc semYield(c: PContext, n: PNode): PNode = elif c.p.owner.typ[0] != nil: localError(c.config, n.info, errGenerated, "yield statement must yield a value") -proc lookUpForDefined(c: PContext, i: PIdent, onlyCurrentScope: bool): PSym = - if onlyCurrentScope: - result = localSearchInScope(c, i) - else: - result = searchInScopes(c, i) # no need for stub loading +proc semDefined(c: PContext, n: PNode): PNode = + checkSonsLen(n, 2, c.config) + # we replace this node by a 'true' or 'false' node: + result = newIntNode(nkIntLit, 0) + result.intVal = ord isDefined(c.config, considerQuotedIdent(c, n[1], n).s) + result.info = n.info + result.typ = getSysType(c.graph, n.info, tyBool) -proc lookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym = +proc lookUpForDeclared(c: PContext, n: PNode, onlyCurrentScope: bool): PSym = case n.kind - of nkIdent: - result = lookUpForDefined(c, n.ident, onlyCurrentScope) + of nkIdent, nkAccQuoted: + result = if onlyCurrentScope: + localSearchInScope(c, considerQuotedIdent(c, n)) + else: + searchInScopes(c, considerQuotedIdent(c, n)) of nkDotExpr: result = nil if onlyCurrentScope: return checkSonsLen(n, 2, c.config) - var m = lookUpForDefined(c, n[0], onlyCurrentScope) + var m = lookUpForDeclared(c, n[0], onlyCurrentScope) if m != nil and m.kind == skModule: let ident = considerQuotedIdent(c, n[1], n) if m == c.module: result = strTableGet(c.topLevelScope.symbols, ident) else: result = strTableGet(m.tab, ident) - of nkAccQuoted: - result = lookUpForDefined(c, considerQuotedIdent(c, n), onlyCurrentScope) of nkSym: result = n.sym of nkOpenSymChoice, nkClosedSymChoice: @@ -1885,15 +1888,11 @@ proc lookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym = localError(c.config, n.info, "identifier expected, but got: " & renderTree(n)) result = nil -proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode = +proc semDeclared(c: PContext, n: PNode, onlyCurrentScope: bool): PNode = checkSonsLen(n, 2, c.config) # we replace this node by a 'true' or 'false' node: result = newIntNode(nkIntLit, 0) - if not onlyCurrentScope and considerQuotedIdent(c, n[0], n).s == "defined": - let d = considerQuotedIdent(c, n[1], n) - result.intVal = ord isDefined(c.config, d.s) - elif lookUpForDefined(c, n[1], onlyCurrentScope) != nil: - result.intVal = 1 + result.intVal = ord lookUpForDeclared(c, n[1], onlyCurrentScope) != nil result.info = n.info result.typ = getSysType(c.graph, n.info, tyBool) @@ -2187,10 +2186,13 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = result = semTypeOf(c, n) of mDefined: markUsed(c, n.info, s) - result = semDefined(c, setMs(n, s), false) - of mDefinedInScope: + result = semDefined(c, setMs(n, s)) + of mDeclared: + markUsed(c, n.info, s) + result = semDeclared(c, setMs(n, s), false) + of mDeclaredInScope: markUsed(c, n.info, s) - result = semDefined(c, setMs(n, s), true) + result = semDeclared(c, setMs(n, s), true) of mCompiles: markUsed(c, n.info, s) result = semCompiles(c, setMs(n, s), flags) diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index 3366732ca..a80b1d057 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -228,7 +228,7 @@ proc semGenericStmt(c: PContext, n: PNode, var mixinContext = false if s != nil: incl(s.flags, sfUsed) - mixinContext = s.magic in {mDefined, mDefinedInScope, mCompiles, mAstToStr} + mixinContext = s.magic in {mDefined, mDeclared, mDeclaredInScope, mCompiles, mAstToStr} let whichChoice = if s.id in ctx.toBind: scClosed elif s.isMixedIn: scForceOpen else: scOpen diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 1315e8960..fd4635ea5 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1834,7 +1834,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, result = semProcAnnotation(c, n, validPragmas) if result != nil: return result result = n - checkSonsLen(n, bodyPos + 1, c.config) + checkMinSonsLen(n, bodyPos + 1, c.config) var s: PSym var typeIsDetermined = false var isAnon = false diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 8700d9a47..4be84d659 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -2324,9 +2324,11 @@ proc matchesAux(c: PContext, n, nOrig: PNode, formal: PSym # current routine parameter template noMatch() = + c.mergeShadowScope #merge so that we don't have to resem for later overloads m.state = csNoMatch m.firstMismatch.arg = a m.firstMismatch.formal = formal + return template checkConstraint(n: untyped) {.dirty.} = if not formal.constraint.isNil: @@ -2335,7 +2337,6 @@ proc matchesAux(c: PContext, n, nOrig: PNode, inc(m.genericMatches, 100) else: noMatch() - return if formal.typ.kind in {tyVar}: let argConverter = if arg.kind == nkHiddenDeref: arg[0] else: arg @@ -2343,11 +2344,9 @@ proc matchesAux(c: PContext, n, nOrig: PNode, if argConverter.typ.kind notin {tyVar}: m.firstMismatch.kind = kVarNeeded noMatch() - return elif not n.isLValue: m.firstMismatch.kind = kVarNeeded noMatch() - return m.state = csMatch # until proven otherwise m.firstMismatch = MismatchInfo() @@ -2359,6 +2358,9 @@ proc matchesAux(c: PContext, n, nOrig: PNode, formal = if formalLen > 1: m.callee.n[1].sym else: nil while a < n.len: + + c.openShadowScope + if a >= formalLen-1 and f < formalLen and m.callee.n[f].typ.isVarargsUntyped: formal = m.callee.n[f].sym incl(marker, formal.position) @@ -2383,12 +2385,10 @@ proc matchesAux(c: PContext, n, nOrig: PNode, if n[a][0].kind != nkIdent: localError(c.config, n[a].info, "named parameter has to be an identifier") noMatch() - return formal = getNamedParamFromList(m.callee.n, n[a][0].ident) if formal == nil: # no error message! noMatch() - return if containsOrIncl(marker, formal.position): m.firstMismatch.kind = kAlreadyGiven # already in namedParams, so no match @@ -2397,7 +2397,6 @@ proc matchesAux(c: PContext, n, nOrig: PNode, # different parameter names could match later on): when false: localError(n[a].info, errCannotBindXTwice, formal.name.s) noMatch() - return m.baseTypeMatch = false m.typedescMatched = false n[a][1] = prepareOperand(c, formal.typ, n[a][1]) @@ -2407,7 +2406,6 @@ proc matchesAux(c: PContext, n, nOrig: PNode, m.firstMismatch.kind = kTypeMismatch if arg == nil: noMatch() - return checkConstraint(n[a][1]) if m.baseTypeMatch: #assert(container == nil) @@ -2448,16 +2446,13 @@ proc matchesAux(c: PContext, n, nOrig: PNode, checkConstraint(n[a]) else: noMatch() - return else: m.firstMismatch.kind = kExtraArg noMatch() - return else: if m.callee.n[f].kind != nkSym: internalError(c.config, n[a].info, "matches") noMatch() - return formal = m.callee.n[f].sym m.firstMismatch.kind = kTypeMismatch if containsOrIncl(marker, formal.position) and container.isNil: @@ -2465,7 +2460,6 @@ proc matchesAux(c: PContext, n, nOrig: PNode, # positional param already in namedParams: (see above remark) when false: localError(n[a].info, errCannotBindXTwice, formal.name.s) noMatch() - return if formal.typ.isVarargsUntyped: if container.isNil: @@ -2482,7 +2476,6 @@ proc matchesAux(c: PContext, n, nOrig: PNode, n[a], nOrig[a]) if arg == nil: noMatch() - return if m.baseTypeMatch: assert formal.typ.kind == tyVarargs #assert(container == nil) @@ -2511,8 +2504,13 @@ proc matchesAux(c: PContext, n, nOrig: PNode, localError(c.config, n[a].info, "cannot convert $1 to $2" % [ typeToString(n[a].typ), typeToString(formal.typ) ]) noMatch() - return checkConstraint(n[a]) + + if m.state == csMatch and not(m.calleeSym != nil and m.calleeSym.kind in {skTemplate, skMacro}): + c.mergeShadowScope + else: + c.closeShadowScope + inc(a) # for some edge cases (see tdont_return_unowned_from_owned test case) m.firstMismatch.arg = a @@ -2544,7 +2542,7 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) = if m.state == csNoMatch: return # check that every formal parameter got a value: for f in 1..<m.callee.n.len: - var formal = m.callee.n[f].sym + let formal = m.callee.n[f].sym if not containsOrIncl(marker, formal.position): if formal.ast == nil: if formal.typ.kind == tyVarargs: |