Transitive R-Value Inference and Move Construction a la Rust
Nordlöw via Digitalmars-d
digitalmars-d at puremagic.com
Mon Sep 26 08:24:35 PDT 2016
I just discovered the following interesting fact about the
current state of DMD:
/// Sample struct that keeps track of the number of copy
constructions (postblits) that is made in a `C`-instance.
struct C
{
...
this(this) // postblit
{
++copyCount; // yet another reference
}
struct RCStore
{
}
uint copyCount = 0; ///< copy counter
}
/// Empty
void f(T)(T a)
{
assert(a.copyCount == 1);
}
/// Top function.
void top(T)(T a) // TODO infer that `a` is passed
as an r-value?
{
assert(a.copyCount == 0);
sub(a); // so we can do move construction
here aswell?
}
/// Sub function.
void sub(T)(T a)
{
assert(a.copyCount == 1); // this is not neccessary
}
unittest
{
import std.stdio : writeln;
C x;
f(x);
assert(x.copyCount == 0);
const y = x;
assert(y.copyCount == 1);
top(C());
}
namely that D will infer move semantics of `top`'s parameter when
passing an r-value in the call to `top()` but not transitively in
`top`'s call to `sub` even though this is possible.
What stops us from extending D's introspection possibilities to
also provide us with knowledge about whether `C` was called with
an r-value? Thereby making it possible to infer r-value
referenceness, and in turn move semantics, of (templated)
function parameters transitively.
A problem here is that the number of different template
instantiations of a function will grow exponentially with the
number of the function parameters that have a postblit. But then
again aren't we all interested in maximum performance here and
reduce the need for GC usage here in the case when the postblit
does GC-allocated duplication of `C`-local allocations?
If template bloat will be a problem an alternative solution could
be to add yet another trait, say, `__traits(isRValue, a)` the
tells whether the parameter `a` was called using an r-value. That
together with `static if` could branch transitive parameter
passing semantics when needed. However, the code generation for
such a template would not be affected if this trait is never used
and code generation among templates not differing in call
semantics could be reused.
This would make D even more competitive with Rust especially in
the case when chaining lazy ranges with containers with
allocating post-blits.
I realize that this is a somewhat competing approach to what is
currently being worked on in DIP-1000.
I'm using DMD git master.
Destroy!
More information about the Digitalmars-d
mailing list