From a055f628f4354f6125e97c42bcf83f8e20149fac Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Sat, 31 Aug 2019 09:49:47 +0100 Subject: [PATCH 1/2] fixes #12092 --- compiler/semstmts.nim | 4 ++-- tests/destructor/tdestructor_too_late.nim | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 tests/destructor/tdestructor_too_late.nim diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 5a0aac40e3..dff67f175e 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1595,7 +1595,7 @@ proc semOverride(c: PContext, s: PSym, n: PNode) = else: break if obj.kind in {tyObject, tyDistinct, tySequence, tyString}: obj = canonType(c, obj) - if obj.destructor.isNil: + if obj.destructor.isNil and tfCheckedForDestructor notin obj.flags: obj.attachedOps[attachedDestructor] = s else: prevDestructor(c, obj.destructor, obj, n.info) @@ -1660,7 +1660,7 @@ proc semOverride(c: PContext, s: PSym, n: PNode) = obj = canonType(c, obj) #echo "ATTACHING TO ", obj.id, " ", s.name.s, " ", cast[int](obj) let k = if name == "=": attachedAsgn else: attachedSink - if obj.attachedOps[k].isNil: + if obj.attachedOps[k].isNil and tfCheckedForDestructor notin obj.flags: obj.attachedOps[k] = s else: prevDestructor(c, obj.attachedOps[k], obj, n.info) diff --git a/tests/destructor/tdestructor_too_late.nim b/tests/destructor/tdestructor_too_late.nim new file mode 100644 index 0000000000..d279280ba1 --- /dev/null +++ b/tests/destructor/tdestructor_too_late.nim @@ -0,0 +1,14 @@ +discard """ + errmsg: "cannot bind another '=destroy' to: Obj; previous declaration was constructed here implicitly: tdestructor_too_late.nim(7, 16)" +""" +type Obj* = object + v*: int + +proc something(this: sink Obj) = + discard + +proc `=destroy`(this: var Obj) = + echo "igotdestroyed" + this.v = -1 + +var test* = Obj(v: 42) \ No newline at end of file From a388c35741b4e9718ddd1d1f781a56f6bc0373c0 Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Sat, 31 Aug 2019 09:56:39 +0100 Subject: [PATCH 2/2] support forward declared destructors --- compiler/semstmts.nim | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index dff67f175e..262deba5eb 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1595,7 +1595,9 @@ proc semOverride(c: PContext, s: PSym, n: PNode) = else: break if obj.kind in {tyObject, tyDistinct, tySequence, tyString}: obj = canonType(c, obj) - if obj.destructor.isNil and tfCheckedForDestructor notin obj.flags: + if obj.attachedOps[attachedDestructor] == s: + discard "forward declared destructor" + elif obj.destructor.isNil and tfCheckedForDestructor notin obj.flags: obj.attachedOps[attachedDestructor] = s else: prevDestructor(c, obj.destructor, obj, n.info) @@ -1660,7 +1662,9 @@ proc semOverride(c: PContext, s: PSym, n: PNode) = obj = canonType(c, obj) #echo "ATTACHING TO ", obj.id, " ", s.name.s, " ", cast[int](obj) let k = if name == "=": attachedAsgn else: attachedSink - if obj.attachedOps[k].isNil and tfCheckedForDestructor notin obj.flags: + if obj.attachedOps[k] == s: + discard "forward declared op" + elif obj.attachedOps[k].isNil and tfCheckedForDestructor notin obj.flags: obj.attachedOps[k] = s else: prevDestructor(c, obj.attachedOps[k], obj, n.info)