summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2015-10-27 08:37:56 +0100
committerAraq <rumpf_a@web.de>2015-10-27 08:37:56 +0100
commit86e2d6ee907d4573fecfd2faded6e700cf75c8a3 (patch)
tree97ae5e8cdc8867f230f2355433b18ae2dc868cb9
parente94a6ec1f91c855ef1e5a2b54db7a5cbe8d245d4 (diff)
downloadNim-86e2d6ee907d4573fecfd2faded6e700cf75c8a3.tar.gz
fixes #3476
-rw-r--r--compiler/seminst.nim4
-rw-r--r--tests/generics/tvarseq_caching.nim48
2 files changed, 50 insertions, 2 deletions
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index f9a137740..2c767ffc6 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -243,14 +243,14 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   # generic[void](), generic[int]()
   # see ttypeor.nim test.
   var i = 0
-  newSeq(entry.concreteTypes, fn.typ.len+gp.len)
+  newSeq(entry.concreteTypes, fn.typ.len+gp.len-1)
   for s in instantiateGenericParamList(c, gp, pt):
     addDecl(c, s)
     entry.concreteTypes[i] = s.typ
     inc i
   pushProcCon(c, result)
   instantiateProcType(c, pt, result, info)
-  for j in 0 .. result.typ.len-1:
+  for j in 1 .. result.typ.len-1:
     entry.concreteTypes[i] = result.typ.sons[j]
     inc i
   if tfTriggersCompileTime in result.typ.flags:
diff --git a/tests/generics/tvarseq_caching.nim b/tests/generics/tvarseq_caching.nim
new file mode 100644
index 000000000..f617b9335
--- /dev/null
+++ b/tests/generics/tvarseq_caching.nim
@@ -0,0 +1,48 @@
+discard """
+  output: '''@[1, 2, 3]
+@[4.0, 5.0, 6.0]
+@[1, 2, 3]
+@[4.0, 5.0, 6.0]
+@[1, 2, 3]
+@[4, 5, 6]'''
+"""
+
+# bug #3476
+
+proc foo[T]: var seq[T] =
+  ## Problem! Bug with generics makes every call to this proc generate
+  ## a new seq[T] instead of retrieving the `items {.global.}` variable.
+  var items {.global.}: seq[T]
+  return items
+
+proc foo2[T]: ptr seq[T] =
+  ## Workaround! By returning by `ptr` instead of `var` we can get access to
+  ## the `items` variable, but that means we have to explicitly deref at callsite.
+  var items {.global.}: seq[T]
+  return addr items
+
+proc bar[T]: var seq[int] =
+  ## Proof. This proc correctly retrieves the `items` variable. Notice the only thing
+  ## that's changed from `foo` is that it returns `seq[int]` instead of `seq[T]`.
+  var items {.global.}: seq[int]
+  return items
+
+
+foo[int]() = @[1, 2, 3]
+foo[float]() = @[4.0, 5.0, 6.0]
+
+foo2[int]()[] = @[1, 2, 3]
+foo2[float]()[] = @[4.0, 5.0, 6.0]
+
+bar[int]() = @[1, 2, 3]
+bar[float]() = @[4, 5, 6]
+
+
+echo foo[int]()      # prints 'nil' - BUG!
+echo foo[float]()    # prints 'nil' - BUG!
+
+echo foo2[int]()[]   # prints '@[1, 2, 3]'
+echo foo2[float]()[] # prints '@[4.0, 5.0, 6.0]'
+
+echo bar[int]()      # prints '@[1, 2, 3]'
+echo bar[float]()    # prints '@[4, 5, 6]'