summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim3
-rw-r--r--compiler/sem.nim15
-rw-r--r--compiler/semdata.nim10
-rw-r--r--compiler/semexprs.nim3
-rw-r--r--compiler/seminst.nim7
-rw-r--r--compiler/semstmts.nim1
-rw-r--r--compiler/semtempl.nim2
-rw-r--r--compiler/semtypes.nim9
-rw-r--r--compiler/transf.nim5
-rw-r--r--tests/template/tgensymregression.nim13
-rw-r--r--tests/template/tparams_gensymed.nim9
11 files changed, 60 insertions, 17 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 8fbec64cf..4ea68dc99 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 dbf237635..961d9fa75 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 20fd1d9be..845efd25a 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 9972585c7..542d7b4e3 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 9c57be023..1a96b4bc6 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 .. <safeLen(n): freshGenSyms(n.sons[i], owner, orig, symMap)
 
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 25d4b3c74..e2b0f4b7a 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1345,6 +1345,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
 proc determineType(c: PContext, s: PSym) =
   if s.typ != nil: return
   #if s.magic != mNone: return
+  #if s.ast.isNil: return
   discard semProcAux(c, s.ast, s.kind, {}, stepDetermineType)
 
 proc semIterator(c: PContext, n: PNode): PNode =
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index a69fe477b..8819f17cc 100644
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -172,7 +172,7 @@ proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym =
   result = newSym(kind, considerQuotedIdent(n), c.owner, n.info)
   incl(result.flags, sfGenSym)
   incl(result.flags, sfShadowed)
-  if c.scopeN == 0: incl(result.flags, sfFromGeneric)
+  #if c.scopeN == 0: incl(result.flags, sfFromGeneric)
 
 proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
   # locals default to 'gensym':
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 17c065b49..440edd226 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -297,7 +297,7 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
 
 proc semTypeIdent(c: PContext, n: PNode): PSym =
   if n.kind == nkSym:
-    result = n.sym
+    result = getGenSym(c, n.sym)
   else:
     when defined(nimfix):
       result = pickSym(c, n, skType)
@@ -1319,8 +1319,9 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
           prev.id = s.typ.id
         result = prev
   of nkSym:
-    if n.sym.kind == skType and n.sym.typ != nil:
-      var t = n.sym.typ
+    let s = getGenSym(c, n.sym)
+    if s.kind == skType and s.typ != nil:
+      var t = s.typ
       let alias = maybeAliasType(c, t, prev)
       if alias != nil:
         result = alias
@@ -1332,7 +1333,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
       markUsed(n.info, n.sym)
       styleCheckUse(n.info, n.sym)
     else:
-      if n.sym.kind != skError: localError(n.info, errTypeExpected)
+      if s.kind != skError: localError(n.info, errTypeExpected)
       result = newOrPrevType(tyError, prev, c)
   of nkObjectTy: result = semObjectNode(c, n, prev)
   of nkTupleTy: result = semTuple(c, n, prev)
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 13c6dd8fe..cbd1f15e3 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -869,7 +869,10 @@ proc transform(c: PTransf, n: PNode): PTransNode =
     else:
       result = transformSons(c, n)
   of nkIdentDefs, nkConstDef:
-    result = transformSons(c, n)
+    result = n.PTransNode
+    #transformSons(c, n)
+    let L = n.len-1
+    result[L] = transform(c, n.sons[L])
     # XXX comment handling really sucks:
     if importantComments():
       PNode(result).comment = n.comment
diff --git a/tests/template/tgensymregression.nim b/tests/template/tgensymregression.nim
index e73ff258d..e49678fec 100644
--- a/tests/template/tgensymregression.nim
+++ b/tests/template/tgensymregression.nim
@@ -19,3 +19,16 @@ proc foo(): void =
   echo repr(v1 *** v2)
 
 foo()
+
+# bug #5383
+import sequtils
+
+proc zipWithIndex[A](ts: seq[A]): seq[(int, A)] =
+  toSeq(pairs(ts))
+
+proc main =
+  discard zipWithIndex(@["foo", "bar"])
+  discard zipWithIndex(@[1, 2])
+  discard zipWithIndex(@[true, false])
+
+main()
diff --git a/tests/template/tparams_gensymed.nim b/tests/template/tparams_gensymed.nim
index 6c4413866..568725fd4 100644
--- a/tests/template/tparams_gensymed.nim
+++ b/tests/template/tparams_gensymed.nim
@@ -5,8 +5,8 @@ import macros
 
 # Test that parameters are properly gensym'ed finally:
 
-template genNodeKind(kind, name: expr): stmt =
-  proc name*(children: varargs[PNimrodNode]): PNimrodNode {.compiletime.}=
+template genNodeKind(kind, name: untyped) =
+  proc name*(children: varargs[NimNode]): NimNode {.compiletime.}=
     result = newNimNode(kind)
     for c in children:
       result.add(c)
@@ -22,7 +22,7 @@ type Something = object
 
 proc testA(x: Something) = discard
 
-template def(name: expr) {.immediate.} =
+template def(name: untyped) =
   proc testB[T](reallyUniqueName: T) =
     `test name`(reallyUniqueName)
 def A
@@ -35,8 +35,7 @@ testB(x)
 # Test that templates in generics still work (regression to fix the
 # regression...)
 
-template forStatic(index: expr, slice: Slice[int], predicate: stmt):
-                   stmt {.immediate.} =
+template forStatic(index, slice, predicate: untyped) =
   const a = slice.a
   const b = slice.b
   when a <= b: