* fixes #18469 * Update compiler/injectdestructors.nim
This commit is contained in:
parent
cf0cf32d27
commit
f8519657c4
4 changed files with 74 additions and 15 deletions
|
|
@ -774,7 +774,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
|
||||||
result = passCopyToSink(n, c, s)
|
result = passCopyToSink(n, c, s)
|
||||||
else:
|
else:
|
||||||
case n.kind
|
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.
|
# Let C(x) be the construction, 'x' the vector of arguments.
|
||||||
# C(x) either owns 'x' or it doesn't.
|
# C(x) either owns 'x' or it doesn't.
|
||||||
# If C(x) owns its data, we must consume C(x).
|
# 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"
|
# don't destroy it"
|
||||||
# but if C(x) is a ref it MUST own its data since we must 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'.
|
# 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 mode == normal: normal
|
||||||
let m = if isRefConstr: sinkArg
|
|
||||||
elif mode == normal: normal
|
|
||||||
else: sinkArg
|
else: sinkArg
|
||||||
|
|
||||||
result = copyTree(n)
|
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:
|
if n[i].kind == nkExprColonExpr:
|
||||||
result[i][1] = p(n[i][1], c, s, m)
|
result[i][1] = p(n[i][1], c, s, m)
|
||||||
elif n[i].kind == nkRange:
|
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)
|
result[i][1] = p(n[i][1], c, s, m)
|
||||||
else:
|
else:
|
||||||
result[i] = p(n[i], c, s, m)
|
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:
|
if mode == normal and isRefConstr:
|
||||||
result = ensureDestruction(result, n, c, s)
|
result = ensureDestruction(result, n, c, s)
|
||||||
of nkCallKinds:
|
of nkCallKinds:
|
||||||
|
|
|
||||||
|
|
@ -2229,16 +2229,6 @@ proc genTupleConstr(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
r.res.addf("Field$#: $#", [i.rope, a.res])
|
r.res.addf("Field$#: $#", [i.rope, a.res])
|
||||||
r.res.add("}")
|
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) =
|
proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
var a: TCompRes
|
var a: TCompRes
|
||||||
r.kind = resExpr
|
r.kind = resExpr
|
||||||
|
|
|
||||||
|
|
@ -1656,3 +1656,13 @@ proc isSinkTypeForParam*(t: PType): bool =
|
||||||
result = false
|
result = false
|
||||||
else:
|
else:
|
||||||
result = true
|
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
|
||||||
|
|
|
||||||
44
tests/arc/tcursor_field_obj_constr.nim
Normal file
44
tests/arc/tcursor_field_obj_constr.nim
Normal 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()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue