How can I set finalizers on both parent and child types when using arc?
https://play.nim-lang.org/#ix=3ME7
type
Parent* = ref object of RootObj
Child* = ref object of Parent
proc setup*(self: Parent) =
echo "Parent setup"
proc delete*(self: Parent) =
echo "Parent delete"
proc newParent*(): Parent =
echo "Parent newParent"
new(result, delete)
result.setup
proc setup(self: Child) =
self.Parent.setup
echo "Child setup"
proc delete*(self: Child) =
echo "Child delete"
self.Parent.delete
proc newChild*(): Child =
echo "Child newChild"
new(result, delete)
result.setup
proc main = discard newChild()
if isMainModule:
main()
GC_fullCollect()
output with --gc:refc
Child newChild
Parent setup
Child setup
Child delete
Parent delete
output with --gc:arc
Error: cannot bind another '=destroy' to: Child:ObjectType; previous declaration was constructed here implicitly
I think it is a bug but possibly unfixable, --gc:arc tries to turn finalizers into destructors but the design of these two features is different.
A workaround is to use explicit destructors:
type
Parent* = ref object of RootObj
Child* = ref object of Parent
proc setup*(self: Parent) =
echo "Parent setup"
proc `=destroy`(self: var typeof(Parent()[])) =
echo "Parent delete"
proc delete*(self: Parent) =
`=destroy`(self[])
proc newParent*(): Parent =
echo "Parent newParent"
new(result)
result.setup
proc `=destroy`(self: var typeof(Child()[])) =
echo "Child delete"
`=destroy` cast[Parent](addr self)[] # better way to call parent destructor ?
proc delete*(self: Child) =
`=destroy`(self[])
proc setup(self: Child) =
self.Parent.setup
echo "Child setup"
proc newChild*(): Child =
echo "Child newChild"
new(result)
result.setup
proc main = discard newChild()
if isMainModule:
main()
GC_fullCollect()
@filcuc if what @guibar says this is real, this is a showstopper for current NimQml design + arc.
Better to stick with --gc:refc and consider it a requirement, or branch code ad compile time:
Maybe there's a third option to use =destroy but keep overloading of prod delete working in object hierarchy?
This works with --gc:arc:
https://play.nim-lang.org/#ix=3MR7
type
Parent* = object of RootObj
Child* = object of Parent
proc `=destroy`*(self: var Parent) =
echo "Parent delete"
proc `=destroy`*(self: var Child) =
echo "Child delete"
self.Parent.`=destroy`
proc setup*(self: ref Parent) =
echo "Parent setup"
proc newParent*(): ref Parent =
echo "Parent newParent"
new(result)
result.setup
proc setup(self: ref Child) =
let p: ref Parent = self
p.setup
echo "Child setup"
proc newChild*(): ref Child =
echo "Child newChild"
new(result)
result.setup
proc main = discard newChild()
if isMainModule:
main()
GC_fullCollect()
#[
Outputs:
Child newChild
Parent setup
Child setup
Child delete
Parent delete
]#