Type | Also known as | GC'ed | Can be nil | Can form cycle |
seq | Sequences | True | False (previously true) | (normally) False |
string | Strings | True | False (previously true) | False |
cstring | Compatible strings | False | True | False |
ref | (Traced) references | True | True | True |
ptr | Pointers | False | True | True |
proc {.closure.} | Closures | True | True | True |
(proc) and not (proc {.closure.}) | Non-closure procedural types | False | True | False |
By simplifing the above, we get:
\\ | Can be nil | Can not be nil |
GC'ed | ref, closures | string, seq |
Not GC'ed | ptr, cstring, non-closure procedural types | Most of the other types |
I'm still learning Nim, so maybe I am not seeing enough details, but I find this table to be logical. I do have a very strong C/C++/ASM/... background, and have long ago written my own Turbo Pascal compiler so maybe that's why I see it that way.
Things like a seq and string are objects that are 'constructed' and 'destructed', so they clean up after themselves when they leave scope.
Pointers are pointing at other things that should clean up themselves, so it's logical that they don't clean up.
I don't know about closures, I believe they will become (like all procs, on any scope) static code on a lower level and then they are never cleaned up nor should they be. They are not like closures in scripted languages where GCing them is necessary and expected.
This should be put into the manual somewhere!
As for the closure thing they get turned into a pointer to a normal procedure and a pointer to an environment. This environment contains all the state captured by the closure. When the closure is called it's actually a static procedure which is called, but it is given the environment pointer to work as a closure. Because of this environment they are GC'ed as the environment must be freed at some point.