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
]#