* fixes #18469

* Update compiler/injectdestructors.nim
This commit is contained in:
Andreas Rumpf
2021-07-20 22:15:06 +02:00
committed by GitHub
parent cf0cf32d27
commit f8519657c4
4 changed files with 74 additions and 15 deletions

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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()