summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim6
-rw-r--r--compiler/seminst.nim26
-rw-r--r--compiler/semtypinst.nim2
-rw-r--r--compiler/sigmatch.nim20
-rw-r--r--tests/closure/tfib50.nim10
-rw-r--r--tests/closure/tissue1642.nim1
-rw-r--r--tests/generics/twrong_field_caching.nim68
7 files changed, 113 insertions, 20 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 18b6e6b37..b327218a1 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -1298,6 +1298,12 @@ proc initIdTable(x: var TIdTable) =
   x.counter = 0
   newSeq(x.data, StartSize)
 
+proc resetIdTable*(x: var TIdTable) =
+  x.counter = 0
+  # clear and set to old initial size:
+  setLen(x.data, 0)
+  setLen(x.data, StartSize)
+
 proc initObjectSet(x: var TObjectSet) = 
   x.counter = 0
   newSeq(x.data, StartSize)
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 3d2427a89..d74584096 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -174,17 +174,27 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
   result.n = originalParams.shallowCopy
   
   for i in 1 .. <result.len:
+    # twrong_field_caching requires these 'resetIdTable' calls:
+    if i > 1: resetIdTable(cl.symMap)
     result.sons[i] = replaceTypeVarsT(cl, result.sons[i])
     propagateToOwner(result, result.sons[i])
-    let param = replaceTypeVarsN(cl, originalParams[i])
-    result.n.sons[i] = param
-    if param.kind == nkSym:
-      # XXX: this won't be true for void params
-      # implement pass-through of void params and
-      # the "sort by distance to point" container
+    internalAssert originalParams[i].kind == nkSym
+    when true:
+      let oldParam = originalParams[i].sym
+      let param = copySym(oldParam)
+      param.owner = prc
+      param.typ = result.sons[i]
+      param.ast = oldParam.ast.copyTree
+      # don't be lazy here and call replaceTypeVarsN(cl, originalParams[i])!
+      result.n.sons[i] = newSymNode(param)
+      addDecl(c, param)
+    else:
+      let param = replaceTypeVarsN(cl, originalParams[i])
+      result.n.sons[i] = param
       param.sym.owner = prc
-      addDecl(c, param.sym)
-    
+      addDecl(c, result.n.sons[i].sym)
+
+  resetIdTable(cl.symMap)
   result.sons[0] = replaceTypeVarsT(cl, result.sons[0])
   result.n.sons[0] = originalParams[0].copyTree
   
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 9688520f3..12fce1b84 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -223,7 +223,7 @@ proc lookupTypeVar(cl: var TReplTypeVars, t: PType): PType =
     result = errorType(cl.c)
     # In order to prevent endless recursions, we must remember
     # this bad lookup and replace it with errorType everywhere.
-    # These code paths are only active in nimrod check
+    # These code paths are only active in "nim check"
     idTablePut(cl.typeMap, t, result)
   elif result.kind == tyGenericParam and not cl.allowMetaTypes:
     internalError(cl.info, "substitution with generic parameter")
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index e6e43d78c..a782658b6 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -1261,12 +1261,20 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
       result = implicitConv(nkHiddenStdConv, f, result, m, c)
   of isGeneric:
     inc(m.genericMatches)
-    result = copyTree(arg)
-    result.typ = getInstantiatedType(c, arg, m, f)
-    # BUG: f may not be the right key!
-    if skipTypes(result.typ, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
-      result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
-      # BUGFIX: use ``result.typ`` and not `f` here
+    when false:
+      if skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple:
+        result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
+      else:
+        result = arg.copyTree
+    else:
+      # XXX Why is this ever necessary? arg's type should not be retrofitted
+      # to match formal's type in this way!
+      result = copyTree(arg)
+      result.typ = getInstantiatedType(c, arg, m, f)
+      # BUG: f may not be the right key!
+      if skipTypes(result.typ, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
+        result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
+        # BUGFIX: use ``result.typ`` and not `f` here
   of isFromIntLit:
     # too lazy to introduce another ``*matches`` field, so we conflate
     # ``isIntConv`` and ``isIntLit`` here:
diff --git a/tests/closure/tfib50.nim b/tests/closure/tfib50.nim
index 21a4afa9a..719aa3ad5 100644
--- a/tests/closure/tfib50.nim
+++ b/tests/closure/tfib50.nim
@@ -4,16 +4,16 @@ discard """
 
 import tables
 
-proc memoize(f: proc (a: int): int): proc (a: int): int =
-    var previous = initTable[int, int]()
-    return proc(i: int): int =
+proc memoize(f: proc (a: int64): int64): proc (a: int64): int64 =
+    var previous = initTable[int64, int64]()
+    return proc(i: int64): int64 =
         if not previous.hasKey i:
             previous[i] = f(i)
         return previous[i]
 
-var fib: proc(a: int): int
+var fib: proc(a: int64): int64
 
-fib = memoize(proc (i: int): int =
+fib = memoize(proc (i: int64): int64 =
     if i == 0 or i == 1:
         return 1
     return fib(i-1) + fib(i-2)
diff --git a/tests/closure/tissue1642.nim b/tests/closure/tissue1642.nim
index d396630c8..e3028c88e 100644
--- a/tests/closure/tissue1642.nim
+++ b/tests/closure/tissue1642.nim
@@ -1,5 +1,6 @@
 discard """
   file: "tissue1642.nim"
+  disabled: true
 """
 block:
   var i = 0
diff --git a/tests/generics/twrong_field_caching.nim b/tests/generics/twrong_field_caching.nim
new file mode 100644
index 000000000..595c58eb7
--- /dev/null
+++ b/tests/generics/twrong_field_caching.nim
@@ -0,0 +1,68 @@
+discard """
+  output: '''a23: 2x3
+a32: 3x2
+transpose A
+t32: 3x2
+transpose B
+x23: 2x3 (2x3)
+x32: 3x2 (3x2)'''
+"""
+
+# bug #2125
+# Suppose we have the following type for a rectangular array:
+
+type
+  RectArray*[R, C: static[int], T] = distinct array[R * C, T]
+ 
+var a23: RectArray[2, 3, int]
+var a32: RectArray[3, 2, int]
+ 
+echo "a23: ", a23.R, "x", a23.C
+echo "a32: ", a32.R, "x", a32.C
+
+# Output:
+# a23: 2x3
+# a32: 3x2
+
+# Looking good. Let's add a proc:
+proc transpose*[R, C, T](m: RectArray[R, C, T]): RectArray[C, R, T] =
+  echo "transpose A"
+
+var t32 = a23.transpose
+
+echo "t32: ", t32.R, "x", t32.C
+
+# Output:
+# t32: 3x2
+ 
+ 
+# Everything is still OK. Now let's use the rectangular array inside another
+# generic type:
+type
+  Matrix*[R, C: static[int], T] = object
+    theArray*: RectArray[R, C, T]
+
+#var m23: Matrix[2, 3, int]
+#var m32: Matrix[3, 2, int]
+
+#echo "m23: ", m23.R, "x", m23.C, " (", m23.theArray.R, "x", m23.theArray.C, ")"
+#echo "m32: ", m32.R, "x", m32.C, " (", m32.theArray.R, "x", m32.theArray.C, ")"
+
+# Output:
+# m23: 2x3 (2x3)
+# m32: 3x2 (3x2)
+
+
+# Everything is still as expected. Now let's add the following proc:
+proc transpose*[R, C, T](m: Matrix[R, C, T]): Matrix[C, R, T] =
+  echo "transpose B"
+
+var x23: Matrix[2, 3, int]
+var x32 = x23.transpose
+
+echo "x23: ", x23.R, "x", x23.C, " (", x23.theArray.R, "x", x23.theArray.C, ")"
+echo "x32: ", x32.R, "x", x32.C, " (", x32.theArray.R, "x", x32.theArray.C, ")"
+ 
+# Output:
+# x23: 2x3 (2x3)
+# x32: 3x2 (3x2)  <--- this is incorrect. R and C do not match!