diff --git a/Destructors.rest b/Destructors.rest index 7d66de3..799d88e 100644 --- a/Destructors.rest +++ b/Destructors.rest @@ -25,8 +25,7 @@ A ``sink`` parameter conveys a transfer of ownership. The parameter will be *con A ``sink`` parameter is internally **not** mapped to ``var``, instead the usual "pass-by-copy" / "optimize to by-ref if more efficient" implementation -is used. However, similar rules apply -- you cannot pass a ``const`` to -a ``sink`` parameter. +is used. A ``sink`` parameter **must** be **consumed** exactly once within the proc's body. The compiler will use a dataflow analysis to prove this fact. @@ -51,7 +50,7 @@ Use after consume ----------------- 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 -to eliminate copies. Instead of doing the copy at ``location = sinkParam`` it's turned into a sink and then +to eliminate copies (and destructions). Instead of doing the copy at ``location = sinkParam`` it's turned into a sink and then *at* the callsite you can specify a *move* if it's not already an expression of the form ``lastReadOf(z)``. 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 @@ -140,9 +139,10 @@ Rule Pattern Transformed into 4.1 sinkParam = y `=sink`(sinkParam, y) 4.2 x = y `=`(x, y) # a copy 5.1 f_sink(g()) f_sink(g()) -5.2 f_sink(y) f_sink(y); reset(y) - # 'reset(y)' for locals usually optimized away -5.3 f_noSink(g()) var tmp = bitwiseCopy(g()); f(tmp); `=destroy`(tmp) +5.2 f_sink(y) f_sink(copy y); + # copy unless we can see it's the last read +5.3 f_sink(move y) f_sink(y); reset(y) # explicit moves empties 'y' +5.4 f_noSink(g()) var tmp = bitwiseCopy(g()); f(tmp); `=destroy`(tmp) ======== ==================== ===========================================================