Well, here is a self contained example:
type
O1 = ref object of RootObj
i: int
O2 = ref object of O1
j: int
proc finalizeGObject*[T](o: T) =
echo "finalizeGObject"
#proc xadd(self: O1; widget: O2) =
# discard
proc xadd(self: O1; widget: O1) =
discard
proc main() =
var
o1: O1
o2: O2
new(o1, finalizeGObject)
new(o2, finalizeGObject)
o1.xadd(o2)
o2 = nil
GC_fullCollect()
main()
For this I get no output, so finalizer is not called.
But with this
proc xadd(self: O1; widget: O2) =
discard
#proc xadd(self: O1; widget: O1) =
# discard
we get
$ ./t1
finalizeGObject