This page is a follow-up of https://nim-lang.org/araq/destructors.html and further outlines of where Nim is heading in the future. (Did I hear anyone say "Nim v2"?)
Nim's strings and sequences should become "GC-free" implementations and are exemplary for how Nim's core should work. Strings and sequences are value-based that means ``=`` performs a copy (conceptually). In practice many copies can be optimized away (see my blog post). The "optimized" copy is called a "move" and is supported via the type bound operator ``=sink``.
After having read https://codesynthesis.com/~boris/blog//2012/06/19/efficient-argument-passing-cxx11-part1/ I have changed my mind about how ``sink`` parameters need to work. ``sink`` parameters are purely an optimization
This is much simpler than the original idea of introducing a "use after consume" error state that empties the container and would to lead to error prone code constructs just to save some object copies. It also implies we don't need yet another overloading disambiguation rule, a table's put proc can look like
to keep the produced code size small. There is a ``system.move`` proc that can be used to annotate the moves at callsite that can further eliminate copies.
``sink T`` and ``lent T`` introduce further rewrite rules but lead to more efficient code. Even better, these rules optimize away create/copy <-> destroy pairs and so can also make atomic reference counting more efficient by eliminating incref <-> decref pairs.
A ``sink`` parameter cannot be passed to its destructor since the destructor takes a ``var T`` parameter and ``sink`` itself cannot be passed as ``var``.
**Solution**: The destructor call is done on a temporary location that was bitcopied from the ``sink`` parameter or conceptually via ``unsafeAddr``. **Proof** that this is safe: After the destruction the ``sink`` parameter won't be used again. At the callsite either a copy was passed to the ``sink`` parameter which can't be used again either or an explicit ``move`` was performed which resets the memory and ensures that the it won't be used afterwards too. (Maybe this indicates that the destructor should also be a ``sink`` parameter and the ``reset`` step usually done in the destructor can be done by the compiler if required.)
Flaw 2
======
An analysis like "every code path provable leads to the parameters consumption" is hard to pull off, especially in a language like Nim with exceptions.
**Solution**: The analysis can introduce a fallback path with hidden bool flags like ``if not flag: =destroy(sinkParam)``. Furthermore the compiler should probably get even smarter in its inference of ``raises: []``.
Passing a value ``x`` to an object or array constructor as in ``MyObject(field: x)`` is conceptually the same as ``=sink(myobj.field, x)``. This still needs to be implemented.