@Araq, as I have mentioned in other posts, I am trying to apply some of the new memory management ideas under the current version 0.20.0 system, with problems as follows:
1\. The "old" closures aren't compatible with what closures will be as they rely on a (local) GC'ed ref to an environment structure, but one can work around that by wrapping "old" closures in an object with a sidecar ForeignCell field which contains the state of protect called on the environment pointer when created and dispose called on this field for destruction, thus making it look like the new closures that will rely on owned ref to do this. This is a kludgy but viable work around which should mean there are minimal changes when the new closures are available. 2\. My major problem is due to the different syntax and use of the old =sink versus the new =move as per the new destructor spec 2: > under the old design so called "self assignments" could not work. > Consequence: sink parameters for objects that have a non-trivial destructor > must be passed as by-pointer under the hood. A further advantage is that > parameters are never destroyed, only variables are. The caller's location > passed to a sink parameter has to be destroyed by the caller and does not > burden the callee. (with the following problem example:) from ranom import randomize, rand proc select(cond: bool; a, b: sink string): string = if cond: result = a # moves a into result else: result = b # moves b into result proc main = var x = "abc" var y = "xyz" # possible self-assignment: x = select(rand(1.0) < 0.5, x, y) # 'select' must communicate what parameter has been # consumed. We cannot simply generate: # (select(...); wasMoved(x); wasMoved(y)) # NOTE, WE DON'T HAVE TO; IT JUST WORKS... Run However, it seems that things have been fixed so the above example does work in Nim version 0.20.0 with the compiler using a combination of the hooks and ismoved called on the parameter that is used and not on the other one; the main difference between as it works now and as proposed in Destructors spec 2 seems to be the different type signature on =sink than =move with the current one having a var only on the destination parameter where the second has a var on both parameters, and what the compiler is doing underneath rather than combining the destination destruction and source resetting in the assignment and moving "hooks" The new =move[T](dst, src: var T) not available yet has a different type signature than the =sink[T](dst: var T; src: T) it functionally replaces due to having to modify its source to reset it to show that it has been transferred (an implicit move); As these are automatically invoked when ownership is transferred under move semantics along with "cheats" so that the var parameter can be applied to a let variable, the only work around is to make all bindings to which we want to apply it var's and not let's and manually invoke a move on the source of the sink parameter when in the sink proc. I don't know enough about the implementation details to know what is the easiest way, but it seems to me that a decision should be made whether to use the current =sink syntax or the new =move syntax (along with the changed definition of all of the "hooks") so that there aren't breaking changes forward. In other words, it seems to me that the new Destructors spec 2 has two distinct parts as follows: 1. Redefinition of the move semantics and syntax 2. Possible implementation of the new non-GC'ed ref T and owned ref T If implemented as per the spec, the first would be a breaking change due to the different signature of the =move hook and I would recommend that, if desired, it be included pre-version 1.0. This doesn't seem to be risky at all as the functionality seems to be the same as currently, although it could break some libraries due to the different syntax. The second isn't very much a breaking change other than making such kludges as are necessary to make closures work across threads no longer be necessary and requiring an occasional owned, and as you say the compiler will guide where those are necessary. As this is relatively untested as yet, it likely should be deferred to a later point upgrade version or version 2.0. If somehow development of the second could be accelerated to be included in version 1.0 if it works, it would make me happy ;-)