summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/transf.nim22
-rw-r--r--tests/array/tarray.nim25
2 files changed, 40 insertions, 7 deletions
diff --git a/compiler/transf.nim b/compiler/transf.nim
index c4da48d53..21295662a 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -555,17 +555,22 @@ proc transformConv(c: PTransf, n: PNode): PTransNode =
 
 type
   TPutArgInto = enum
-    paDirectMapping, paFastAsgn, paVarAsgn, paComplexOpenarray
+    paDirectMapping, paFastAsgn, paFastAsgnTakeTypeFromArg
+    paVarAsgn, paComplexOpenarray
 
 proc putArgInto(arg: PNode, formal: PType): TPutArgInto =
   # This analyses how to treat the mapping "formal <-> arg" in an
   # inline context.
   if formal.kind == tyTypeDesc: return paDirectMapping
   if skipTypes(formal, abstractInst).kind in {tyOpenArray, tyVarargs}:
-    if arg.kind == nkStmtListExpr:
+    case arg.kind
+    of nkStmtListExpr:
       return paComplexOpenarray
-    return paDirectMapping    # XXX really correct?
-                              # what if ``arg`` has side-effects?
+    of nkBracket:
+      return paFastAsgnTakeTypeFromArg
+    else:
+      return paDirectMapping    # XXX really correct?
+                                # what if ``arg`` has side-effects?
   case arg.kind
   of nkEmpty..nkNilLit:
     result = paDirectMapping
@@ -645,12 +650,15 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
     # can happen for 'nim check':
     if i >= ff.n.len: return result
     var formal = ff.n.sons[i].sym
-    case putArgInto(arg, formal.typ)
+    let pa = putArgInto(arg, formal.typ)
+    case pa
     of paDirectMapping:
       idNodeTablePut(newC.mapping, formal, arg)
-    of paFastAsgn:
+    of paFastAsgn, paFastAsgnTakeTypeFromArg:
       var t = formal.typ
-      if formal.ast != nil and formal.ast.typ.destructor != nil and t.destructor == nil:
+      if pa == paFastAsgnTakeTypeFromArg:
+        t = arg.typ
+      elif formal.ast != nil and formal.ast.typ.destructor != nil and t.destructor == nil:
         t = formal.ast.typ # better use the type that actually has a destructor.
       elif t.destructor == nil and arg.typ.destructor != nil:
         t = arg.typ
diff --git a/tests/array/tarray.nim b/tests/array/tarray.nim
index 6fa305064..30244173a 100644
--- a/tests/array/tarray.nim
+++ b/tests/array/tarray.nim
@@ -28,6 +28,13 @@ dflfdjkl__abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajsdf
 kgdchlfniambejop
 fjpmholcibdgeakn
 2.0
+a:1
+a:2
+a:3
+ret:
+ret:1
+ret:12
+123
 '''
 joinable: false
 """
@@ -557,3 +564,21 @@ block arrayLiterals:
   doAssert [1: 2][1] == 2
   doAssert [-1'i8: 2][-1] == 2
   doAssert [-1'i8: 2, 3, 4, 5].Idx is range[-1'i8..2'i8]
+
+
+
+# bug #8316
+
+proc myAppend[T](a:T):string=
+  echo "a:", a
+  return $a
+
+template append2*(args: varargs[string, myAppend]): string =
+  var ret:string
+  for a in args:
+    echo "ret:", ret
+    ret.add(a)
+  ret
+
+let foo = append2("1", "2", "3")
+echo foo