diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2021-07-20 22:15:06 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-20 22:15:06 +0200 |
commit | f8519657c43f458db9c915cec62c59022041eb05 (patch) | |
tree | baad0a54d733312a55e495d877c3847f928a02e4 | |
parent | cf0cf32d276002e850a87667fff62c4df12999d6 (diff) | |
download | Nim-f8519657c43f458db9c915cec62c59022041eb05.tar.gz |
fixes #18469 (#18544)
* fixes #18469 * Update compiler/injectdestructors.nim
-rw-r--r-- | compiler/injectdestructors.nim | 25 | ||||
-rw-r--r-- | compiler/jsgen.nim | 10 | ||||
-rw-r--r-- | compiler/types.nim | 10 | ||||
-rw-r--r-- | tests/arc/tcursor_field_obj_constr.nim | 44 |
4 files changed, 74 insertions, 15 deletions
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index 6e4eaa817..cf09b3ff5 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -774,7 +774,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode = result = passCopyToSink(n, c, s) else: case n.kind - of nkBracket, nkObjConstr, nkTupleConstr, nkClosure, nkCurly: + of nkBracket, nkTupleConstr, nkClosure, nkCurly: # Let C(x) be the construction, 'x' the vector of arguments. # C(x) either owns 'x' or it doesn't. # If C(x) owns its data, we must consume C(x). @@ -785,13 +785,11 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode = # don't destroy it" # but if C(x) is a ref it MUST own its data since we must destroy it # so then we have no choice but to use 'sinkArg'. - let isRefConstr = n.kind == nkObjConstr and n.typ.skipTypes(abstractInst).kind == tyRef - let m = if isRefConstr: sinkArg - elif mode == normal: normal + let m = if mode == normal: normal else: sinkArg result = copyTree(n) - for i in ord(n.kind in {nkObjConstr, nkClosure})..<n.len: + for i in ord(n.kind == nkClosure)..<n.len: if n[i].kind == nkExprColonExpr: result[i][1] = p(n[i][1], c, s, m) elif n[i].kind == nkRange: @@ -799,6 +797,23 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode = result[i][1] = p(n[i][1], c, s, m) else: result[i] = p(n[i], c, s, m) + of nkObjConstr: + # see also the remark about `nkTupleConstr`. + let isRefConstr = n.typ.skipTypes(abstractInst).kind == tyRef + let m = if isRefConstr: sinkArg + elif mode == normal: normal + else: sinkArg + + result = copyTree(n) + for i in 1..<n.len: + if n[i].kind == nkExprColonExpr: + let field = lookupFieldAgain(n.typ, n[i][0].sym) + if field != nil and sfCursor in field.flags: + result[i][1] = p(n[i][1], c, s, normal) + else: + result[i][1] = p(n[i][1], c, s, m) + else: + result[i] = p(n[i], c, s, m) if mode == normal and isRefConstr: result = ensureDestruction(result, n, c, s) of nkCallKinds: diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 4b89b0cde..85947535e 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -2229,16 +2229,6 @@ proc genTupleConstr(p: PProc, n: PNode, r: var TCompRes) = r.res.addf("Field$#: $#", [i.rope, a.res]) r.res.add("}") -proc lookupFieldAgain(ty: PType; field: PSym): PSym = - var ty = ty - while ty != nil: - ty = ty.skipTypes(skipPtrs) - assert(ty.kind in {tyTuple, tyObject}) - result = lookupInRecord(ty.n, field.name) - if result != nil: break - ty = ty[0] - if result == nil: result = field - proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) = var a: TCompRes r.kind = resExpr diff --git a/compiler/types.nim b/compiler/types.nim index 49ebb1dae..0a50af56e 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -1656,3 +1656,13 @@ proc isSinkTypeForParam*(t: PType): bool = result = false else: result = true + +proc lookupFieldAgain*(ty: PType; field: PSym): PSym = + var ty = ty + while ty != nil: + ty = ty.skipTypes(skipPtrs) + assert(ty.kind in {tyTuple, tyObject}) + result = lookupInRecord(ty.n, field.name) + if result != nil: break + ty = ty[0] + if result == nil: result = field diff --git a/tests/arc/tcursor_field_obj_constr.nim b/tests/arc/tcursor_field_obj_constr.nim new file mode 100644 index 000000000..b87f734bd --- /dev/null +++ b/tests/arc/tcursor_field_obj_constr.nim @@ -0,0 +1,44 @@ +discard """ + output: '''a +b +c''' + cmd: "nim c --gc:arc $file" +""" + +# bug #18469 + +type + Edge = object + neighbor {.cursor.}: Node + + NodeObj = object + neighbors: seq[Edge] + label: string + visited: bool + Node = ref NodeObj + + Graph = object + nodes: seq[Node] + +proc `=destroy`(x: var NodeObj) = + echo x.label + `=destroy`(x.neighbors) + `=destroy`(x.label) + +proc addNode(self: var Graph; label: string): Node = + self.nodes.add(Node(label: label)) + result = self.nodes[^1] + +proc addEdge(self: Graph; source, neighbor: Node) = + source.neighbors.add(Edge(neighbor: neighbor)) + +proc main = + var graph: Graph + let nodeA = graph.addNode("a") + let nodeB = graph.addNode("b") + let nodeC = graph.addNode("c") + + graph.addEdge(nodeA, neighbor = nodeB) + graph.addEdge(nodeA, neighbor = nodeC) + +main() |