Move and CTFE

Q. Schroll qs.il.paperinik at gmail.com
Wed May 30 22:42:13 UTC 2018


On Wednesday, 30 May 2018 at 21:02:07 UTC, Jonathan M Davis wrote:
> On Wednesday, May 30, 2018 20:42:38 Q. Schroll via 
> Digitalmars-d-learn wrote:
>> It seems one cannot std.algorithm.mutation.move objects 
>> explicitly. Say I have a non-copyable type
>> [...]
>> It fails because move() cannot be executed at compile time. The
>> reason
>>      "memcpy cannot be interpreted at compile time, because it 
>> has
>> no available source code"
>> sounds very suspicious.
>
> Why is it suspicious? memcpy is a C function, and you can't 
> call C functions during CTFE precisely because the compiler 
> doesn't have their source code. You can't call D functions 
> either if the compiler doesn't have their source (e.g. if 
> you're using a .di file to hide the implementation).

I definitely do understand the error message and it makes sense 
that it fails the way it's implemented. However, it makes no 
sense that moving as a concept can fail at CTFE. That's what I 
find suspicious. [Maybe 'suspicious' isn't the right term; I 
couldn't express it better.] You can move rvalues at CTFE which 
proves that the compiler can do it.

>> Shouldn't it be possible to move at CTFE,
>> too, or does it mean, non-copyable types are practically 
>> unusable
>> for CTFE?
>
> You can't do much in the way of pointer or memory manipulation 
> during CTFE (e.g. no pointer arithmetic or reinterpret casts). 
> So, I don't see how a move could be done during CTFE. Even if 
> the source for memcpy were available during CTFE, I suspect 
> that it wouldn't be allowed due to the lower level stuff that 
> it does.

That's the explanation why probably all currently possible 
library alternatives to memcpy would fail. I suspected that when 
encountering the error, but still wonder why memcpy or other 
low-level stuff is even necessary to accomplish something the 
compiler is perfectly able to do.

 From what I see, the reason for the hack is lack of 
expressiveness: We don't have rvalue-refs in D (which I find 
good) so, currently, there is no cast-solution as in C++. So for 
a proper move() that works at CTFE, we'd need some specific tool.

I have no idea of the details on how the compiler handles 
lvalues. Would it make sense to add a compiler trait, 
specifically to solve moving? Like __traits(move, 
lvalue_expression) [name up for discussion] that is identical to 
lvalue_expression with the exception that the (lvalue/rvalue) 
flag (or whatever it is) is set to "rvalue". Basically, it's the 
C++ solution: After the "cast", the compiler will proceed and 
pretend it is an rvalue and therefore initiate moving.

Do you think adding a trait to make move() and swap() work at 
CTFE is worth it?

A quick search showed me the class "Expression" has "virtual bool 
isLvalue();" so it might be easy as wrapping and hooking that 
virtual method. To me, [1] highly suggests that it works.

[1] 
https://github.com/dlang/dmd/blob/master/src/dmd/expression.d#L1219



More information about the Digitalmars-d-learn mailing list