diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index bf02060558..e57898ae8d 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -91,17 +91,23 @@ proc optimize(s: var Scope) = filterNil(wasMoved) filterNil(final) -proc toTree(s: var Scope; ret: PNode; onlyCareAboutVars = false): PNode = +type + ToTreeFlag = enum + onlyCareAboutVars, + producesValue + +proc toTree(s: var Scope; ret: PNode; flags: set[ToTreeFlag]): PNode = if not s.needsTry: optimize(s) assert ret != nil if s.vars.len == 0 and s.final.len == 0 and s.wasMoved.len == 0: # trivial, nothing was done: result = ret else: - if isEmptyType(ret.typ): - result = newNodeI(nkStmtList, ret.info) - else: + let isExpr = producesValue in flags and not isEmptyType(ret.typ) + if isExpr: result = newNodeIT(nkStmtListExpr, ret.info, ret.typ) + else: + result = newNodeI(nkStmtList, ret.info) if s.vars.len > 0: let varSection = newNodeI(nkVarSection, ret.info) @@ -109,7 +115,7 @@ proc toTree(s: var Scope; ret: PNode; onlyCareAboutVars = false): PNode = varSection.add newTree(nkIdentDefs, newSymNode(tmp), newNodeI(nkEmpty, ret.info), newNodeI(nkEmpty, ret.info)) result.add varSection - if onlyCareAboutVars: + if onlyCareAboutVars in flags: result.add ret s.vars.setLen 0 elif s.needsTry: @@ -117,8 +123,11 @@ proc toTree(s: var Scope; ret: PNode; onlyCareAboutVars = false): PNode = for m in s.wasMoved: finSection.add m for i in countdown(s.final.high, 0): finSection.add s.final[i] result.add newTryFinally(ret, finSection) + elif isExpr: + for m in s.wasMoved: result.add m + for i in countdown(s.final.high, 0): result.add s.final[i] + result.add ret else: - #assert isEmptyType(ret.typ) result.add ret for m in s.wasMoved: result.add m for i in countdown(s.final.high, 0): result.add s.final[i] @@ -593,22 +602,25 @@ proc pVarTopLevel(v: PNode; c: var Con; s: var Scope; ri, res: PNode) = elif ri.kind != nkEmpty: res.add moveOrCopy(v, ri, c, s, isDecl = true) -template handleNestedTempl(n: untyped, processCall: untyped) = +template handleNestedTempl(n, processCall: untyped; alwaysStmt: bool) = template maybeVoid(child, s): untyped = if isEmptyType(child.typ): p(child, c, s, normal) else: processCall(child, s) + let treeFlags = if not isEmptyType(n.typ) and not alwaysStmt: {producesValue} else: {} case n.kind of nkStmtList, nkStmtListExpr: # a statement list does not open a new scope if n.len == 0: return n result = copyNode(n) + if alwaysStmt: result.typ = nil for i in 0..---------transformed-to--------->" echo renderTree(result, {renderIds}) diff --git a/tests/destructor/tmove_objconstr.nim b/tests/destructor/tmove_objconstr.nim index 5366f49574..0740bd46b7 100644 --- a/tests/destructor/tmove_objconstr.nim +++ b/tests/destructor/tmove_objconstr.nim @@ -113,7 +113,7 @@ proc myfunc2(x, y: int): tuple[a: MySeqNonCopyable, b:int, c:MySeqNonCopyable] = var cc = newMySeq(y, 5.0) (a: case x: of 1: - let (z1, z2) = myfunc(x,y) + let (z1, z2) = myfunc(x, y) z2 elif x > 5: raise newException(ValueError, "new error") else: newMySeq(x, 1.0),