diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index b621e99b99..c515ba1d4d 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -261,6 +261,11 @@ proc isLastRead(n: PNode; c: var Con): bool = template interestingSym(s: PSym): bool = s.owner == c.owner and s.kind in InterestingSyms and hasDestructor(s.typ) +template isUnpackedTuple(s: PSym): bool = + ## we move out all elements of unpacked tuples, + ## hence unpacked tuples themselves don't need to be destroyed + s.kind == skTemp and s.typ.kind == tyTuple + proc patchHead(n: PNode) = if n.kind in nkCallKinds and n[0].kind == nkSym and n.len > 1: let s = n[0].sym @@ -446,6 +451,13 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode = ri2.add pArg(ri[i], c, i < L and parameters[i].kind == tySink) #recurse(ri, ri2) result.add ri2 + of nkBracketExpr: + if ri[0].kind == nkSym and isUnpackedTuple(ri[0].sym): + # unpacking of tuple: move out the elements + result = genSink(c, dest.typ, dest, ri) + else: + result = genCopy(c, dest.typ, dest, ri) + result.add p(ri, c) of nkObjConstr: result = genSink(c, dest.typ, dest, ri) let ri2 = copyTree(ri) @@ -454,6 +466,17 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode = # so these all act like 'sink' parameters: ri2[i].sons[1] = pArg(ri[i][1], c, isSink = true) result.add ri2 + of nkTupleConstr: + result = genSink(c, dest.typ, dest, ri) + let ri2 = copyTree(ri) + for i in 0.. 0: + result.data = cast[ptr UncheckedArray[float]](createShared(float, size)) + + result.setTo(initial_value) + +proc myfunc(x, y: int): (MySeqNonCopyable, MySeqNonCopyable) = + result = (newMySeq(x, 1.0), newMySeq(y, 5.0)) + +proc myfunc2(x, y: int): tuple[a: MySeqNonCopyable, b:int, c:MySeqNonCopyable] = + (a: newMySeq(x, 1.0), b:0, c:newMySeq(y, 5.0)) + +let (seq1, seq2) = myfunc(2, 3) +doAssert seq1.len == 2 +doAssert seq1[0] == 1.0 +doAssert seq2.len == 3 +doAssert seq2[0] == 5.0 + +var (seq3, i, _) = myfunc2(2, 3) +doAssert seq3.len == 2 +doAssert seq3[0] == 1.0 \ No newline at end of file