mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 05:50:30 +00:00
* fixes #18469 * Update compiler/injectdestructors.nim
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
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()
|
||||
Reference in New Issue
Block a user