From 00ccdec2383802a9d0ddc72dc6808bf2df28e04f Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sat, 6 Jul 2019 20:02:50 +0200 Subject: [PATCH] fixes #8316 (#11673) (cherry picked from commit 64e14089203ae5532360966f348e96ce8d7ea676) --- compiler/transf.nim | 22 +++++++++++++++------- tests/array/tarray.nim | 25 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/compiler/transf.nim b/compiler/transf.nim index c4da48d53b..21295662a7 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 b40c8757c5..07198a4989 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 """ @@ -548,3 +555,21 @@ block t3899: x.a[i] const c = O(a: [1.0,2.0]) echo c[2] + + + +# 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