> Thanks I've actually learned a bit here too. Well, my learning curve was somewhat steeper, thank you again. And if I understood the background sufficiently well, I might have found a reasonable solution for my issue that involves the lessons learned.
For me, it looks sufficiently foolproof, although it involves (a pretty basic) `=destroy`. It keeps the `cached` children as ref objects (yes, far better) and, well, seems to do the trick required ... import tables type SomeEnum = enum PARENT, CHILD RefSomeOne = ref SomeOne SomeOne = object case kind: SomeEnum of PARENT: children: Table[int, RefSomeOne] of CHILD: id: int parent: RefSomeOne ChildErasor = object id: int parent: RefSomeOne proc `=destroy`(x: var ChildErasor) = # The foolproof part: if not x.parent.isNil(): var child: RefSomeOne if x.parent.children.pop(x.id, child): echo "erase child" & $x.id # ------------------------------------------------ # the really important piece (NEVER, NEVER, EVER FORGET!): x.parent = nil proc getChild(parent: RefSomeOne): tuple[child: RefSomeOne, erasor: ChildErasor] = let child_id = parent.children.len() + 1 child = RefSomeOne(kind: CHILD, id: child_id, parent: parent) erasor = ChildErasor(id: child_id, parent: parent) parent.children[child_id] = child result.child = child result.erasor = erasor var parent = RefSomeOne(kind: PARENT) child_1 = parent.getChild() discard child_1 block: var child_2 = parent.getChild() discard child_2 doAssert parent.children.len() == 2 block: var child_3 = parent.getChild() discard child_3 doAssert parent.children.len() == 3 doAssert parent.children.len() == 2 doAssert parent.children.len() == 1 Run Output: [Allocated] 0000000000670040 result: 0000000000670050 [Allocated] 0000000000670070 result: 0000000000670080 [Allocated] 00000000006700A0 result: 00000000006700B0 [Allocated] 00000000006700D0 result: 00000000006700E0 erase child3 [Freed] 00000000006700D0 erase child2 [Freed] 00000000006700A0 erase child1 [Freed] 0000000000670070 [Freed] 0000000000670040 Have also thought about sending Andreas lots of chocolates, sweets and flowers for him to invoke some `at_destroy(x: var T)` (`= default`, if not overloaded) at the very beginning of nim's standard `=destroy` (no clue how costly/possible): It's not too uncommon that something is to be done by standard before destroying object instances (cleanup, tasks etc.). Although it might add some flexibility, avoid repetitive code and be even more foolproof, I think I can live with the above for the moment. Sorry, Andreas, for the chocolate & flowers.