Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto generated destructors for tuples/objects fail with "non-trivial" error... #11671

GordonBGood opened this issue Jul 6, 2019 · 0 comments


Copy link

commented Jul 6, 2019

There are times one wants to call the auto generated =destroy destructor for generic types without being concerned about what types they are or what types they contain. For example, one might define a type that might contain primitive types such as numbers, enum's, set's, proc's, but might also contain pointer's, ptr's, ref's or nested tuples/objects. Currently, one can't just call the =destroy destructor assuming that it will be auto generated correctly.


  TestObj = object
    a, b: int

# following fails with:  Error: internal error: destructor turned out to be not trivial
# var tst0 = (1, 2); tst0.`=destroy`
# following fails with:  Error: internal error: destructor turned out to be not trivial
# var tst1 = TestObj(a: 1, b: 2); tst1.`=destroy`

Expected Output

It should just destroy as @Araq has said it should, destroying each of the fields

Possible Solution

One needs to define a "deepDestroy" overloaded series of proc's as follows and call that from within a custom =destroy destructor to bypass the current behavior:

# this builds stack, but is unlikely to recurse deep enough to cause stack overflow...
# this appears to be the only way to ensure that nested structures containing a combination of
# pointers, (can also be ref's), tuples and objects...
proc deepDestroy[T: SomeNumber | enum | set | proc](x: var T) {.inline.} = discard
proc deepDestroy[T: object | tuple](x: var T) {.inline.} =
  for e in x.fields:
    var ev = e; ev.deepDestroy; x.reset
proc deepDestroy[T: pointer](x: var T) {.inline.} =
  if x != nil: x.dealloc; x.reset
proc deepDestroy[T](x: var ptr T) {.inline.} =
  if x != nil: x[].deepDestroy; x.dealloc; x.reset
proc deepDestroy[T](x: var ref T) {.inline.} =
  if x != nil: x[].deepDestroy; x.reset

Additional Information

  • Your Nim version: 0.20.0
  • Was it working in the previous Nim releases? Don't know, but destructors are quite a new feature

@Araq Araq closed this in 3258c1e Jul 6, 2019

narimiran added a commit that referenced this issue Jul 8, 2019

fixes #11671
(cherry picked from commit 3258c1e)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
2 participants
You can’t perform that action at this time.