Hello, I have a question about destructors. I am not sure if I am misunderstanding something, or if this is a bug. When I declare a constructor for a type, it is not called if an instance of the object is created free in the main module (as opposed to within a proc).

For example, the destructor is not called here.

{.experimental.}

type
  MyObj = object
    a: int

proc `=destroy`(m: MyObj) =
  echo "Destruct"

let x = MyObj(a: 5)

Yet, if I place the declaration of x in a proc, it works fine:

proc works() =
  let x = MyObj(a: 5)

works()

Do I misunderstand where values are deconstructed, or is this an issue for GitHub?

2018-01-05 20:58:18
why should it be called ? x is global and gets never out of scope. 2018-01-06 11:46:37

Well, it is not an issue but I don't get why it doesn't work for a block:

{.experimental.}

type MyObj = object
  a: int

proc `=destroy`(m: MyObj) =
  echo "Destruct"

block:
  let x = MyObj(a: 5)

I find it misleading as a block should create a new scope (therefore x should get out of this new scope). Also, it does so in Fortran, which is how destructing things outside of subprograms is done when needed.

2018-01-06 22:56:13
adrianv, that makes better sense now. Udiknedormin, I agree here. I think that a block should lead to deconstruction. 2018-01-07 14:14:28
Oh yeah, good to know this doesn't work. 2018-01-10 08:17:07

adianv said: why should it be called ? x is global and gets never out of scope.

Global scope should work as any scope, and call destructors when ending. The point of RAII is to bind the lifetime of a resource to the lifetime of an object, and ensure that the resource is released at some point. Your point is valid if the resource is memory, it might not be for other kinds of resources.

2018-01-11 16:31:41
@sendell Not necessarily. Global scope can be unique in some ways, although I agree it could be quite confusing in Nim specifically. That's the way things are in some languages, for example:
  • in C, global variables can't be initialized in a function call (they can in C++)
  • in Fortran, global (both program-level and module-level) variables can't call finalizers (destructors)
  • in Rust, global (static) variables can't call destructors nor allocate anything on the heap during initialization
2018-01-12 14:40:55

Hi,

Is there a regression in the compiler, because the above example doesn't execute the destructor:

{.experimental.}

type
  MyObj = object
    a: int

proc `=destroy`(m: MyObj) =
  echo "Destruct"

proc works() =
  let x = MyObj(a: 5)

works()

I am on Windows 10, Nim Compiler Version 0.18.0 [Windows: i386], MinGW GCC.

2018-03-10 11:16:41

I am on Windows 10, Nim Compiler Version 0.18.0 [Windows: i386], MinGW GCC.

I don't know if that is just for windows 10, I am on ubuntu with 0.18.0 and I am getting the same thing though my code is a little different

{.experimental.}
type thing = object
  x:int
  p:pointer

proc `=destroy`(o:thing):void =
  if o.p != nil: dealloc o.p
  echo "destroyed"

proc op():thing =
  result = thing(x:10,p:alloc(1))
proc work(o:thing):void=
  echo o

proc main() =
  let t= op()
  work(t)
main()
Hint: used config file '/etc/nim.cfg' [Conf]
Hint: system [Processing]
Hint: destruct [Processing]
CC: destruct
Hint:  [Link]
Hint: operation successful (11723 lines compiled; 0.185 sec total; 22.32MiB peakmem; Debug Build) [SuccessX]
Hint: /home/User/Desktop/nim/tests/destruct  [Exec]
(x: 10, p: ...)

2018-03-15 21:43:11
Oh, seems the --newruntime compiler flag is needed for destructors to work.
2018-03-16 22:09:01