diff options
Diffstat (limited to 'tests/arc/tmovebug.nim')
-rw-r--r-- | tests/arc/tmovebug.nim | 288 |
1 files changed, 285 insertions, 3 deletions
diff --git a/tests/arc/tmovebug.nim b/tests/arc/tmovebug.nim index 61105b44e..8ad7c955c 100644 --- a/tests/arc/tmovebug.nim +++ b/tests/arc/tmovebug.nim @@ -73,6 +73,43 @@ bye () () () +1 +destroy +1 +destroy +1 +destroy +copy (self-assign) +1 +destroy +1 +destroy +1 +destroy +destroy +copy +@[(f: 2), (f: 2), (f: 3)] +destroy +destroy +destroy +sink +sink +destroy +copy +(f: 1) +destroy +destroy +part-to-whole assigment: +sink +(children: @[]) +destroy +sink +(children: @[]) +destroy +copy +destroy +(f: 1) +destroy ''' """ @@ -256,7 +293,7 @@ when false: # bug #13456 -iterator combinations[T](s: openarray[T], k: int): seq[T] = +iterator combinations[T](s: openArray[T], k: int): seq[T] = let n = len(s) assert k >= 0 and k <= n var pos = newSeq[int](k) @@ -419,7 +456,7 @@ initFoo7(2) # bug #14902 -iterator zip[T](s: openarray[T]): (T, T) = +iterator zip[T](s: openArray[T]): (T, T) = var i = 0 while i < 10: yield (s[i mod 2], s[i mod 2 + 1]) @@ -556,4 +593,249 @@ let w2 = newWrapper2(1) echo $w2[] let w3 = newWrapper2(-1) -echo $w3[] \ No newline at end of file +echo $w3[] + + +#-------------------------------------------------------------------- +#self-assignments + +# Self-assignments that are not statically determinable will get +# turned into `=copy` calls as caseBracketExprCopy demonstrates. +# (`=copy` handles self-assignments at runtime) + +type + OO = object + f: int + W = object + o: OO + +proc `=destroy`(x: var OO) = + if x.f != 0: + echo "destroy" + x.f = 0 + +proc `=sink`(x: var OO, y: OO) = + `=destroy`(x) + echo "sink" + x.f = y.f + +proc `=copy`(x: var OO, y: OO) = + if x.f != y.f: + `=destroy`(x) + echo "copy" + x.f = y.f + else: + echo "copy (self-assign)" + +proc caseSym = + var o = OO(f: 1) + o = o # NOOP + echo o.f # "1" + # "destroy" + +caseSym() + +proc caseDotExpr = + var w = W(o: OO(f: 1)) + w.o = w.o # NOOP + echo w.o.f # "1" + # "destroy" + +caseDotExpr() + +proc caseBracketExpr = + var w = [0: OO(f: 1)] + w[0] = w[0] # NOOP + echo w[0].f # "1" + # "destroy" + +caseBracketExpr() + +proc caseBracketExprCopy = + var w = [0: OO(f: 1)] + let i = 0 + w[i] = w[0] # "copy (self-assign)" + echo w[0].f # "1" + # "destroy" + +caseBracketExprCopy() + +proc caseDotExprAddr = + var w = W(o: OO(f: 1)) + w.o = addr(w.o)[] # NOOP + echo w.o.f # "1" + # "destroy" + +caseDotExprAddr() + +proc caseBracketExprAddr = + var w = [0: OO(f: 1)] + addr(w[0])[] = addr(addr(w[0])[])[] # NOOP + echo w[0].f # "1" + # "destroy" + +caseBracketExprAddr() + +proc caseNotAConstant = + var i = 0 + proc rand: int = + result = i + inc i + var s = @[OO(f: 1), OO(f: 2), OO(f: 3)] + s[rand()] = s[rand()] # "destroy" "copy" + echo s # @[(f: 2), (f: 2), (f: 3)] + +caseNotAConstant() + +proc potentialSelfAssign(i: var int) = + var a: array[2, OO] + a[i] = OO(f: 1) # turned into a memcopy + a[1] = OO(f: 2) + a[i+1] = a[i] # This must not =sink, but =copy + inc i + echo a[i-1] # (f: 1) + +potentialSelfAssign (var xi = 0; xi) + + +#-------------------------------------------------------------------- +echo "part-to-whole assigment:" + +type + Tree = object + children: seq[Tree] + + TreeDefaultHooks = object + children: seq[TreeDefaultHooks] + +proc `=destroy`(x: var Tree) = echo "destroy" +proc `=sink`(x: var Tree, y: Tree) = echo "sink" +proc `=copy`(x: var Tree, y: Tree) = echo "copy" + +proc partToWholeSeq = + var t = Tree(children: @[Tree()]) + t = t.children[0] # This should be sunk, but with the special transform (tmp = t.children[0]; wasMoved(0); `=sink`(t, tmp)) + + var tc = TreeDefaultHooks(children: @[TreeDefaultHooks()]) + tc = tc.children[0] # Ditto; if this were sunk with the normal transform (`=sink`(t, t.children[0]); wasMoved(t.children[0])) + echo tc # then it would crash because t.children[0] does not exist after the call to `=sink` + +partToWholeSeq() + +proc partToWholeSeqRTIndex = + var i = 0 + var t = Tree(children: @[Tree()]) + t = t.children[i] # See comment in partToWholeSeq + + var tc = TreeDefaultHooks(children: @[TreeDefaultHooks()]) + tc = tc.children[i] # See comment in partToWholeSeq + echo tc + +partToWholeSeqRTIndex() + +type List = object + next: ref List + +proc `=destroy`(x: var List) = echo "destroy" +proc `=sink`(x: var List, y: List) = echo "sink" +proc `=copy`(x: var List, y: List) = echo "copy" + +proc partToWholeUnownedRef = + var t = List(next: new List) + t = t.next[] # Copy because t.next is not an owned ref, and thus t.next[] cannot be moved + +partToWholeUnownedRef() + + +#-------------------------------------------------------------------- +# test that nodes that get copied during the transformation +# (like dot exprs) don't loose their firstWrite/lastRead property + +type + OOO = object + initialized: bool + + C = object + o: OOO + +proc `=destroy`(o: var OOO) = + doAssert o.initialized, "OOO was destroyed before initialization!" + +proc initO(): OOO = + OOO(initialized: true) + +proc initC(): C = + C(o: initO()) + +proc pair(): tuple[a: C, b: C] = + result = (a: initC(), b: initC())# <- when firstWrite tries to find this node to start its analysis it fails, because injectdestructors uses copyTree/shallowCopy + +discard pair() + + +# bug #17450 +proc noConsume(x: OO) {.nosinks.} = echo x + +proc main3 = + var i = 1 + noConsume: + block: + OO(f: i) + +main3() + +# misc +proc smoltest(x: bool): bool = + while true: + if true: return x + +discard smoltest(true) + +# bug #18002 +type + TTypeAttachedOp = enum + attachedAsgn + attachedSink + attachedTrace + + PNode = ref object + discard + +proc genAddrOf(n: PNode) = + assert n != nil, "moved?!" + +proc atomicClosureOp = + let x = PNode() + + genAddrOf: + block: + x + + case attachedTrace + of attachedSink: discard + of attachedAsgn: discard + of attachedTrace: genAddrOf(x) + +atomicClosureOp() + + +template assertEq(a, b: untyped): untyped = + block: + let + aval = a + bval = b + + if aval != bval: + quit "bug!" + +proc convoluted = + let _ = (; + var val1: string; + if true: val1 = "22" + true + ) + + assertEq val1, "22" + assertEq val1, "22" + +convoluted() |