My main concern was with the case where the same ref object is shared among several parent objects. Setting the field to nil in the destructor would have the side effect of decrementing shared object's reference count, and hence delay destroying the ref object until the last parent object is destroyed.
I had thought that, if `=destroy` for the shared object was explicitly called in the parent object's destructor, then the shared object's destructor would be called multiple times - once for each parent object's destruction. This would obviously be a problem. But that turns out not to be the case, as the code example below shows. It appears that calling `=destroy` on an object does not actually destroy it if the reference count is greater than 1. BTW, I also found out that explicitly decrementing the shared object's reference count in the parent's destructor by calling `GC_unref` also works. The two different calls seem to have the same effect. type AObj = object name: string proc `=destroy`(x: AObj) = echo "Destroying A named ", x.name proc newAObj(name: string): ref AObj = result = AObj.new() result.name = name type BObj = object aref: ref AObj name: string proc `=destroy`(x: BObj) = echo "Destroying B named ", x.name # Commenting out **both** statements below causes a leak - the destructor # for aref is never called `=destroy`(x.aref) # Explicit destructor call - this works fine # GC_unref(x.aref) # Explicit reference count decrement - this also works fine proc newBObj(name: string, aref: ref AObj): ref BObj = result = BObj.new() result.aref = aref result.name = name echo "Creating A" var a = newAObj("A#1") echo "Creating B#1" var bobj1 = newBObj("B#1", a) echo "Creating B#2" var bobj2 = newBObj("B#2", a) echo "Setting A outside of parents to NIL" a = nil echo "Setting B#1 to NIL" bobj1 = nil echo "Setting B#2 to NIL" bobj2 = nil echo "... Done" Run