DIP 1014--Hooking D's struct move semantics--Final Review

Shachar Shemesh shachar at weka.io
Sat Jul 14 14:12:57 UTC 2018


On 14/07/18 15:56, Johan Engelen wrote:
> First off: I am trying to wear a strict language lawyer hat. D spec is 
> already very much ill specced which is _very_ problematic for language 
> and compiler development. I am not attacking the proposal in order to 
> kill it. I am merely commenting on points that I feel should be improved.

Wouldn't these comments be better suited for the language spec's PR, then?

I'm asking seriously. There is nothing in this DIP (or just about any 
other one) that can go, unmodified, into the specs. If that's the DIP's 
purpose, then so be it. If not, then I don't see the value.

> 
> OK, so make _that_ explicit. I think there is value in prescribing the 
> precise order of moves (like for construction of members), such that 
> reasoning about code becomes easier.

I disagree.

The member variables at the point of the move are all:
1. Fully initialized.
2. Either move agnostic or know how to handle their own move
3. Oblivious to one another

Obviously, you might wish to spite me by creating a case where any one 
of the above is not true, but the compiler has every right to assume all 
three points above are true. In your hypothetical spite case, your best 
course of action is to leave the members with no opPostMove at all, and 
handle their move in the containing struct's opPostMove, in which case 
you are fully defined.

Assuming all three are correct, the order in which they are moved makes 
no difference.

> If you want the same semantic effect (as I wrote above), then the text 
> should say that the ordering is relaxed.

I have no objection to explicitly stating that exact move order of 
members is undefined.

> 
>>> Why "SHOULD" and not "MUST"?
>>
>> Precisely for the reason you stated above. So that if you want to do 
>> something else, you may.
> 
> Why is that freedom needed?

Because compiler implementers might have a good reason to do something 
besides this. For example, a compiler writer might choose to place the 
actual moving code inside __move_post_blt, and I don't think we should 
stop her.

> The freedom is already provided by 
> user-defined opPostMove?

Different audiences. opPostMove serves the D programmer, __move_post_blt 
serves the compiler.

> 
> I think the language spec doesn't say when a "move" is performed?

I think Walter sees that as an advantage, but I'm not sure.

Either way, the current language spec says structs must have semantics 
that remain correct even if the struct suddenly changes the memory 
address it resides in. The specs + DIP 1014 say that the above is true, 
or the struct must supply an opPostMove that fixes the semantics post-move.

In both cases, *when* the move takes place is irrelevant.

> Or is it enough to define what a "move" is ? (didn't check but I guess 
> the DIP already explains that)
Only implicitly.

> (D's "move" is different from C++'s right?
Yes.

> D's move after exiting a 
> struct's constructor doesn't lead to a destructor call, but D's 
> std.algorithm.mutation.move _does_ call the destructor of the moved 
> source object.)

Depends on which version of move you're referring to.

For example, moveEmplace does not.

I think the correct way to phrase this is to say that D's move *never* 
calls a destructor, but if the move's destination had a valid object in 
it, that one gets destructed.

In a way, C++'s move is the same, except the actual moving of the data 
from the source location to the destination one is up to the programmer, 
and accordingly, so is destructing. Since, logically, a C++ move 
operator always copies, it also has to destruct the source.

Technically, however, it doesn't always. A move assignment operator 
typically just swaps the content of the structs (i.e. - moves the source 
to the destination and the destination to the source), and lets the 
usual rvalue elimination code destruct it.

Shachar


More information about the Digitalmars-d mailing list