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