Skip to content

Commit

Permalink
ARC: closure inside object constructor now works
Browse files Browse the repository at this point in the history
  • Loading branch information
Araq committed Nov 13, 2019
1 parent bcab3ed commit f22d3c7
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 4 deletions.
17 changes: 15 additions & 2 deletions compiler/injectdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -382,9 +382,16 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
# sink parameter (bug #11524). Note that the string implementation is
# different and can deal with 'const string sunk into var'.
result = passCopyToSink(arg, c)
elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkClosure} + nkLiterals:
elif arg.kind in nkLiterals:
result = arg # literal to sink parameter: nothing to do
elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkClosure}:
# object construction to sink parameter: nothing to do
result = arg
result = copyTree(arg)
for i in ord(arg.kind in {nkObjConstr, nkClosure})..<arg.len:
if arg[i].kind == nkExprColonExpr:
result[i][1] = pArg(arg[i][1], c, isSink = true)
else:
result[i] = pArg(arg[i], c, isSink = true)
elif arg.kind == nkSym and isSinkParam(arg.sym):
# Sinked params can be consumed only once. We need to reset the memory
# to disable the destructor which we have not elided
Expand All @@ -396,6 +403,12 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
result = destructiveMoveVar(arg, c)
elif arg.kind in {nkStmtListExpr, nkBlockExpr, nkBlockStmt, nkIfExpr, nkIfStmt, nkCaseStmt}:
handleNested(arg): pArg(node, c, isSink)
elif arg.kind in {nkHiddenSubConv, nkHiddenStdConv, nkConv}:
result = copyTree(arg)
result[1] = pArg(arg[1], c, isSink = true)
elif arg.kind in {nkObjDownConv, nkObjUpConv}:
result = copyTree(arg)
result[0] = pArg(arg[0], c, isSink = true)
else:
# an object that is not temporary but passed to a 'sink' parameter
# results in a copy.
Expand Down
15 changes: 14 additions & 1 deletion tests/destructor/tlists.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
discard """
output: '''Success
output: '''
@[1, 2, 3]
Success
@["a", "b", "c"]
0'''
cmd: '''nim c --gc:destructors $file'''
Expand Down Expand Up @@ -32,7 +34,18 @@ proc tsimpleClosureIterator =
for it in foobar(myc):
echo it

type
LazyList = ref object
c: proc() {.closure.}

proc tlazyList =
let dep = @[1, 2, 3]
var x = LazyList(c: proc () = echo(dep))
x.c()

let startMem = getOccupiedMem()
tlazyList()

mkManyLeaks()
tsimpleClosureIterator()
echo getOccupiedMem() - startMem
2 changes: 1 addition & 1 deletion tests/destructor/tuse_ownedref_after_move.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
discard """
cmd: '''nim c --newruntime $file'''
errormsg: "'=' is not available for type <owned Widget>; requires a copy because it's not the last read of ':envAlt.b1()'; another read is done here: tuse_ownedref_after_move.nim(53, 4)"
errormsg: "'=' is not available for type <owned Button>; requires a copy because it's not the last read of ':envAlt.b1'; another read is done here: tuse_ownedref_after_move.nim(53, 4)"
line: 49
"""

Expand Down

0 comments on commit f22d3c7

Please sign in to comment.