diff options
-rw-r--r-- | compiler/ast.nim | 6 | ||||
-rw-r--r-- | compiler/seminst.nim | 26 | ||||
-rw-r--r-- | compiler/semtypinst.nim | 2 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 20 | ||||
-rw-r--r-- | tests/closure/tfib50.nim | 10 | ||||
-rw-r--r-- | tests/closure/tissue1642.nim | 1 | ||||
-rw-r--r-- | tests/generics/twrong_field_caching.nim | 68 |
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! |