diff --git a/compiler/ast.nim b/compiler/ast.nim index 8fbec64cf1506..4ea68dc996e61 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1541,8 +1541,7 @@ proc skipGenericOwner*(s: PSym): PSym = ## Generic instantiations are owned by their originating generic ## symbol. This proc skips such owners and goes straight to the owner ## of the generic itself (the module or the enclosing proc). - result = if s.kind in skProcKinds and {sfGenSym, sfFromGeneric} * s.flags == - {sfFromGeneric}: + result = if s.kind in skProcKinds and sfFromGeneric in s.flags: s.owner.owner else: s.owner diff --git a/compiler/sem.nim b/compiler/sem.nim index dbf2376357457..961d9fa75e374 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -168,6 +168,16 @@ proc commonType*(x, y: PType): PType = proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = result = newSym(kind, considerQuotedIdent(n), getCurrOwner(), n.info) +proc getGenSym(c: PContext; s: PSym): PSym = + var it = c.p + while it != nil: + result = get(it, s) + if result != nil: + #echo "got from table ", result.name.s, " ", result.info + return result + it = it.next + result = s + proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = proc `$`(kind: TSymKind): string = substr(system.`$`(kind), 2).toLowerAscii @@ -178,6 +188,11 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = if result.kind != kind: localError(n.info, "cannot use symbol of kind '" & $result.kind & "' as a '" & $kind & "'") + if sfGenSym in result.flags and result.kind notin {skTemplate, skMacro, skParam}: + # declarative context, so produce a fresh gensym: + result = copySym(result) + result.ast = n.sym.ast + put(c.p, n.sym, result) # when there is a nested proc inside a template, semtmpl # will assign a wrong owner during the first pass over the # template; we must fix it here: see #909 diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 20fd1d9be54ea..845efd25a060d 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -39,6 +39,7 @@ type next*: PProcCon # used for stacking procedure contexts wasForwarded*: bool # whether the current proc has a separate header bracketExpr*: PNode # current bracket expression (for ^ support) + mapping*: TIdTable TInstantiationPair* = object genericSym*: PSym @@ -147,6 +148,15 @@ proc lastOptionEntry*(c: PContext): POptionEntry = proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next +proc put*(p: PProcCon; key, val: PSym) = + if p.mapping.data == nil: initIdTable(p.mapping) + #echo "put into table ", key.info + p.mapping.idTablePut(key, val) + +proc get*(p: PProcCon; key: PSym): PSym = + if p.mapping.data == nil: return nil + result = PSym(p.mapping.idTableGet(key)) + proc newOptionEntry*(): POptionEntry = new(result) result.options = gOptions diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 9972585c7b05b..542d7b4e39714 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -922,7 +922,8 @@ proc readTypeParameter(c: PContext, typ: PType, return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info) #echo "came here: returned nil" -proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = +proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = + let s = getGenSym(c, sym) case s.kind of skConst: markUsed(n.info, s) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 9c57be0231d3a..1a96b4bc60e6b 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -106,15 +106,16 @@ proc freshGenSyms(n: PNode, owner, orig: PSym, symMap: var TIdTable) = #if n.kind == nkSym and sfGenSym in n.sym.flags: # if n.sym.owner != orig: # echo "symbol ", n.sym.name.s, " orig ", orig, " owner ", n.sym.owner - if n.kind == nkSym and {sfGenSym, sfFromGeneric} * n.sym.flags == {sfGenSym}: # and + if n.kind == nkSym and sfGenSym in n.sym.flags: # and # (n.sym.owner == orig or n.sym.owner.kind in {skPackage}): let s = n.sym var x = PSym(idTableGet(symMap, s)) - if x == nil: + if x != nil: + n.sym = x + when false: x = copySym(s, false) x.owner = owner idTablePut(symMap, s, x) - n.sym = x else: for i in 0 ..