What ever happened to move semantics?
Timon Gehr
timon.gehr at gmx.ch
Wed Feb 28 21:03:03 UTC 2024
On 2/28/24 21:38, Walter Bright wrote:
> On 2/28/2024 6:22 AM, Timon Gehr wrote:
>> On 2/28/24 15:17, Timon Gehr wrote:
>>> ...
>>> What is missing from the DIP?
>>> ...
>>>
>>
>> 19. Explicit moves.
>>
>> There is no way to force that a given occurrence of a variable is the
>> last use and is moved. We can use std.algorithm.move, but the DIP as
>> specified would just move a copy if something is used again.
>
> Forcing a move just sounds like trouble. If it is not the last use, and
> it is moved, then wouldn't the result be undefined behavior?
No, the idea is that the compiler enforces that it is indeed the last
use and produces a compile-time error message if it cannot prove that it
is the case.
> Determining
> last use should be in the purview of the compiler, not the user, so it
> is reliable.
> ...
Yes. It still holds that one may want to make sure that a value is
really moved at a given point. Sometimes this matters. Anyway, this is
by far not the most important point.
> The Ownership/Borrowing system does determine last use, using data flow
> analysis.
>
>
>> What I would like to see is:
>>
>> ```d
>> void main(){
>> S s;
>> foo(move(s));
>> auto t=s; // error, `s` has been moved
>> S s; // ok, can redeclare `s`
>> }
>> ```
>>
>> Maybe there needs to be a parameter annotation that forces a move,
>> then `move` can be implemented in terms of that.
>
> What is the point of declaring another variable of the same name?
From my previous post:
>
> 16. Missing: Redeclaration after Move
>
> ```d
> S s, t;
> func(s); // moved, `s` no longer accessible
> S s = t; // explicit construction via redeclaration
> ```
>
> A nice feature of this is that the type of a variable can be changed on redeclaration. Note that Rust allows this.
This is a relatively common idiom in languages that support moves. It is
annoying if you have to invent a new name for each intermediate result.
One use case would be type state:
File!(FileState.flushed) file = open("file.txt");
File!(FileState.buffered) file = file.write("hello ");
File!(FileState.buffered) file = file.writeln("world!");
// file.close(); // compile time error
File!(FileState.flushed) file = file.flush();
file.close(); // moves "file"
// file.write("hello"); // compile time error
Assume you have some declarations like these and you want to comment out
part of the statements. It would now be annoying to have to rename
variables.
I.e., you want to use the same name for different versions of the same
thing, similarly to how you do not have to change the name of a variable
when assigning to it.
> We already disallow shadowing declarations, and that has prevented a number
> of bugs at least in my own code (they're very difficult to spot with a
> visual check).
The reason why shadowing is error prone is that multiple variables with
overlapping lifetimes are in scope and the compiler arbitrarily picks
one of them. This case is different, as only one variable of the same
name exists at any given time. This is not error prone. Requiring unique
names is more error prone in this case, as you can accidentally copy an
older version of a variable.
Anyway, this is not the most important thing, please do check out the
points I initially included in my review. This point is just something I
had forgotten to include.
More information about the Digitalmars-d
mailing list