Skip to content

Commit 8e57a9f

Browse files
authored
fixes #24719; improves order of destruction (#25060)
fixes #24719
1 parent 478773f commit 8e57a9f

File tree

3 files changed

+70
-15
lines changed

3 files changed

+70
-15
lines changed

compiler/liftdestructors.nim

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -218,23 +218,38 @@ proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode; enforceDefaultOp: bool,
218218
fillBodyObj(c, n[0], body, x, y, enforceDefaultOp = false)
219219
c.filterDiscriminator = oldfilterDiscriminator
220220
of nkRecList:
221-
for t in items(n): fillBodyObj(c, t, body, x, y, enforceDefaultOp, enforceWasMoved)
221+
# destroys in reverse order #24719
222+
if c.kind == attachedDestructor:
223+
for i in countdown(n.len-1, 0):
224+
fillBodyObj(c, n[i], body, x, y, enforceDefaultOp, enforceWasMoved)
225+
else:
226+
for t in items(n): fillBodyObj(c, t, body, x, y, enforceDefaultOp, enforceWasMoved)
222227
else:
223228
illFormedAstLocal(n, c.g.config)
224229

225230
proc fillBodyObjTImpl(c: var TLiftCtx; t: PType, body, x, y: PNode) =
226-
if t.baseClass != nil:
227-
let dest = newNodeIT(nkHiddenSubConv, c.info, t.baseClass)
228-
dest.add newNodeI(nkEmpty, c.info)
229-
dest.add x
230-
var src = y
231-
if c.kind in {attachedAsgn, attachedDeepCopy, attachedSink}:
232-
src = newNodeIT(nkHiddenSubConv, c.info, t.baseClass)
233-
src.add newNodeI(nkEmpty, c.info)
234-
src.add y
235-
236-
fillBody(c, skipTypes(t.baseClass, abstractPtrs), body, dest, src)
237-
fillBodyObj(c, t.n, body, x, y, enforceDefaultOp = false)
231+
template fillBase =
232+
if t.baseClass != nil:
233+
let dest = newNodeIT(nkHiddenSubConv, c.info, t.baseClass)
234+
dest.add newNodeI(nkEmpty, c.info)
235+
dest.add x
236+
var src = y
237+
if c.kind in {attachedAsgn, attachedDeepCopy, attachedSink}:
238+
src = newNodeIT(nkHiddenSubConv, c.info, t.baseClass)
239+
src.add newNodeI(nkEmpty, c.info)
240+
src.add y
241+
242+
fillBody(c, skipTypes(t.baseClass, abstractPtrs), body, dest, src)
243+
template fillFields =
244+
fillBodyObj(c, t.n, body, x, y, enforceDefaultOp = false)
245+
246+
if c.kind == attachedDestructor:
247+
# destroys in reverse order #24719
248+
fillFields()
249+
fillBase()
250+
else:
251+
fillBase()
252+
fillFields()
238253

239254
proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
240255
var hasCase = isCaseObj(t.n)

tests/arc/tdestructor_order.nim

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
discard """
2+
output: '''
3+
destroying d
4+
destroying c
5+
destroying a 2
6+
destroying d
7+
destroying c
8+
destroying a 1
9+
'''
10+
joinable: false
11+
"""
12+
13+
type
14+
Aaaa {.inheritable.} = object
15+
vvvv: int
16+
Bbbb = object of Aaaa
17+
c: Cccc
18+
d: Dddd
19+
Cccc = object
20+
Dddd = object
21+
22+
Holder = object
23+
member: ref Aaaa
24+
25+
proc `=destroy`(v: Cccc) =
26+
echo "destroying c"
27+
28+
proc `=destroy`(v: Dddd) =
29+
echo "destroying d"
30+
31+
proc `=destroy`(v: Aaaa) =
32+
echo "destroying a ", v.vvvv
33+
34+
func makeHolder(vvvv: int): ref Holder =
35+
(ref Holder)(member: (ref Bbbb)(vvvv: vvvv))
36+
37+
block:
38+
var v = makeHolder(1)
39+
var v2 = makeHolder(2)

tests/destructor/tdestructor.nim

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
discard """
2-
output: '''----1
2+
output: '''
3+
----1
34
myobj constructed
45
myobj destroyed
56
----2
@@ -14,8 +15,8 @@ mygeneric3 constructed
1415
mygeneric1 destroyed
1516
----5
1617
mydistinctObj constructed
17-
myobj destroyed
1818
mygeneric2 destroyed
19+
myobj destroyed
1920
------------------8
2021
mygeneric1 destroyed
2122
----6

0 commit comments

Comments
 (0)