www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DIP 1040

reply Manu <turkeyman gmail.com> writes:
So, what's the story with DIP 1040? It's like 3 or 4 years old, it had
community reviews, it appeared to be well received, then... crickets?

Is there a major defect that stalled it?

Walter: Will you consider implementing 1040 as priority? ARM support in DMD
is nice to have, but we've been waiting for move semantics for well over a
decade... and I really need it, like, asap. It's long overdue.
Jul 08
next sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 09/07/2024 2:35 PM, Manu wrote:
 So, what's the story with DIP 1040? It's like 3 or 4 years old, it had 
 community reviews, it appeared to be well received, then... crickets?
 
 Is there a major defect that stalled it?
 
 Walter: Will you consider implementing 1040 as priority? ARM support in 
 DMD is nice to have, but we've been waiting for move semantics for well 
 over a decade... and I really need it, like, asap. It's long overdue.
The last thing that was said publicly is it went back to Weka to consult on it. For anything more up to date you need to talk with Mike (I'm sure he'll reply here later).
Jul 08
parent Mike Parker <aldacron gmail.com> writes:
On Tuesday, 9 July 2024 at 02:40:32 UTC, Richard (Rikki) Andrew 
Cattermole wrote:

 The last thing that was said publicly is it went back to Weka 
 to consult on it.

 For anything more up to date you need to talk with Mike (I'm 
 sure he'll reply here later).
Right. So, Weka gave some feedback. Max was going to update the DIP based on their feedback, but ended up moving on from it. I spoke to Walter late last year about picking it up again, and he said he needed time to dig back into it to figure out where it needed to go, but wanted to put it off until later. I was supposed to get back to him about it again a few months later and I never did. So at this point the delay is on me. So, yes, I know that Walter wanted to get back to it. I'll talk to him about it.
Jul 08
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
https://github.com/dlang/DIPs/blob/master/DIPs/DIP1040.md

We're going to get back on it.
Jul 12
parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 13/07/2024 7:46 AM, Walter Bright wrote:
 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1040.md
 
 We're going to get back on it.
We did some reading and reviewing of it last night. Some observations: 1. It could be simplified greatly if we had type state analysis (blit init over it and be done with it). 2. Its acting in the form of an optimization, rather than trying to be 100% moves only feature. 3. Isolated ala Midori could be used instead, and that buys us ownership transfer for temporal safety. 4. The move constructor isn't great, it is too easily confused. It is closely related to ``opAssign`` so ``opMove`` or ``opAssignMove`` might be better candidates. 5. To make it move only, you can write and then disable the copy constructor (would need documenting). 6. While it can work, the general consensus seems to be the tunings of the design has some ways to go still.
Jul 12
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/12/2024 11:36 PM, Richard (Rikki) Andrew Cattermole wrote:
 On 13/07/2024 7:46 AM, Walter Bright wrote:
 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1040.md

 We're going to get back on it.
We did some reading and reviewing of it last night.
We?
 Some observations:
 
 1. It could be simplified greatly if we had type state analysis (blit init
over 
 it and be done with it).
 2. Its acting in the form of an optimization, rather than trying to be 100% 
 moves only feature.
 3. Isolated ala Midori could be used instead, and that buys us ownership 
 transfer for temporal safety.
 4. The move constructor isn't great, it is too easily confused. It is closely 
 related to ``opAssign`` so ``opMove`` or ``opAssignMove`` might be better 
 candidates.
 5. To make it move only, you can write and then disable the copy constructor 
 (would need documenting).
 6. While it can work, the general consensus seems to be the tunings of the 
 design has some ways to go still.
Consensus of who?
Jul 13
parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 14/07/2024 4:51 AM, Walter Bright wrote:
 On 7/12/2024 11:36 PM, Richard (Rikki) Andrew Cattermole wrote:
 On 13/07/2024 7:46 AM, Walter Bright wrote:
 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1040.md

 We're going to get back on it.
We did some reading and reviewing of it last night.
We?
Oh right, me, Paul, Steven and Timon were talking on Discord, if I remember right. I can see now that it isn't 6 am, that it may come across as more official than it is, sorry!
 Some observations:

 1. It could be simplified greatly if we had type state analysis (blit 
 init over it and be done with it).
 2. Its acting in the form of an optimization, rather than trying to be 
 100% moves only feature.
 3. Isolated ala Midori could be used instead, and that buys us 
 ownership transfer for temporal safety.
 4. The move constructor isn't great, it is too easily confused. It is 
 closely related to ``opAssign`` so ``opMove`` or ``opAssignMove`` 
 might be better candidates.
 5. To make it move only, you can write and then disable the copy 
 constructor (would need documenting).
 6. While it can work, the general consensus seems to be the tunings of 
 the design has some ways to go still.
Consensus of who?
See above, it was the consensus that I saw happening with everyone who was in the discussion. But the most important take away is that while there is some questioning (by myself as to goal), there is nothing that was making us go it can't go in, in some form.
Jul 13
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 7/14/24 08:44, Richard (Rikki) Andrew Cattermole wrote:
 On 14/07/2024 4:51 AM, Walter Bright wrote:
 On 7/12/2024 11:36 PM, Richard (Rikki) Andrew Cattermole wrote:
 On 13/07/2024 7:46 AM, Walter Bright wrote:
 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1040.md

 We're going to get back on it.
We did some reading and reviewing of it last night.
We?
Oh right, me, Paul, Steven and Timon were talking on Discord, if I remember right.
Well, I don't think the presented points describe my position. For the record: I am on board with DIP1040, except for the error-prone design of destructor elision in move constructors and move assignment operators. I think should be explicit. e.g. ```d this(S s){ // perhaps copies some the members of `s` instead of moving them } // destructor of s called here ```d this(S s){ // move out the guts of `s` one by one // ... ignore(s); // explicitly elide destructor call } ``` and/or ```d this(S s){ // destructure and move: this.tupleof = s.moved_tupleof; // s is gone here, no destructor will be called } ```
Jul 14
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 7/14/24 12:39, Timon Gehr wrote:
 ...
 
 For the record: I am on board with DIP1040, except for the error-prone 
 design of destructor elision in move constructors and move assignment 
 operators. I think should be explicit.
 
Of course, even more can be done to make move semantics an even better experience in D, but DIP1040 is a good basis. For example, I would want: - an annotation that ensures a certain use of a variable is a move. (This is important given that the analysis in DIP1040 will need to be incomplete, so it is good to be able to confirm it works where it matters.) - a parameter storage class that enforces the parameter was moved. However, those can be pretty easily built on top of DIP1040. (And they may even be the same feature.)
Jul 14
next sibling parent reply Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Sunday, 14 July 2024 at 10:51:36 UTC, Timon Gehr wrote:
 Of course, even more can be done to make move semantics an even 
 better experience in D, but DIP1040 is a good basis. For 
 example, I would want: […]

 - a parameter storage class that enforces the parameter was 
 moved.
https://forum.dlang.org/post/yiwpmuhgpasanzakzbdd forum.dlang.org Something like this?
Jul 16
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 7/16/24 16:41, Quirin Schroll wrote:
 On Sunday, 14 July 2024 at 10:51:36 UTC, Timon Gehr wrote:
 Of course, even more can be done to make move semantics an even better 
 experience in D, but DIP1040 is a good basis. For example, I would 
 want: […]

 - a parameter storage class that enforces the parameter was moved.
https://forum.dlang.org/post/yiwpmuhgpasanzakzbdd forum.dlang.org Something like this?
Yes, for example. (I think an obvious keyword for this would be `in`, but that is used in different ways now.)
Jul 17
parent Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Wednesday, 17 July 2024 at 18:26:28 UTC, Timon Gehr wrote:
 On 7/16/24 16:41, Quirin Schroll wrote:
 On Sunday, 14 July 2024 at 10:51:36 UTC, Timon Gehr wrote:
 Of course, even more can be done to make move semantics an 
 even better experience in D, but DIP1040 is a good basis. For 
 example, I would want: […]

 - a parameter storage class that enforces the parameter was 
 moved.
https://forum.dlang.org/post/yiwpmuhgpasanzakzbdd forum.dlang.org Something like this?
Yes, for example. (I think an obvious keyword for this would be `in`, but that is used in different ways now.)
Well, if `in` is intended to mean “input-only” parameter, how it’s implemented kind of makes sense, even if it’s hard to use that way.
Jul 17
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/14/2024 3:51 AM, Timon Gehr wrote:
 - a parameter storage class that enforces the parameter was moved.
The caller should make the decision of whether it's a move or a copy, the callee should not care. The callee owns the value (and hence must destruct it) in either case.
Jul 18
next sibling parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 19/07/2024 8:27 AM, Walter Bright wrote:
 On 7/14/2024 3:51 AM, Timon Gehr wrote:
 - a parameter storage class that enforces the parameter was moved.
The caller should make the decision of whether it's a move or a copy, the callee should not care. The callee owns the value (and hence must destruct it) in either case.
I'm starting to seriously question DIP1040's design, if it is even doing what people like Manu or Weka need. Are copies seriously wanted in addition to moving? The whole point of move constructors as far as I understand, is to establish ownership transfer. And this is what Timon here is asking about, the guarantee that it is a unique transfer.
Jul 18
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 7/18/24 22:27, Walter Bright wrote:
 On 7/14/2024 3:51 AM, Timon Gehr wrote:
 - a parameter storage class that enforces the parameter was moved.
The caller should make the decision of whether it's a move or a copy, the callee should not care. The callee owns the value (and hence must destruct it) in either case.
It's simply that often, move is a better default than copy. This is because copies are silent, while use after move will give a diagnostic, forcing an explicit, and visible, opt into the less efficient semantics. Perhaps being able to change the default at the type level might be sufficient. I guess it can kind of be achieved with a private copy constructor.
Jul 18
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Thursday, July 18, 2024 2:41:06 PM MDT Timon Gehr via Digitalmars-d wrote:
 On 7/18/24 22:27, Walter Bright wrote:
 On 7/14/2024 3:51 AM, Timon Gehr wrote:
 - a parameter storage class that enforces the parameter was moved.
The caller should make the decision of whether it's a move or a copy, the callee should not care. The callee owns the value (and hence must destruct it) in either case.
It's simply that often, move is a better default than copy. This is because copies are silent, while use after move will give a diagnostic, forcing an explicit, and visible, opt into the less efficient semantics. Perhaps being able to change the default at the type level might be sufficient. I guess it can kind of be achieved with a private copy constructor.
Given that moving is generally more efficient, I would have thought that what we would want to do is to always move if we can and copy if we can't - which would mean that if we can guarantee that it's the last use of a variable, we'd do a move; otherwise, it would be a copy. A copy constructor then allows the programmer to override what happens with a copy, and a move constructor allows the programmer to override what happens with a move. If the programmer wants to prevent copying and/or moving, then they disable the corresponding constructor. So, in any situation where the compiler can choose between a move and a copy (e.g. when the variable is passed to a function by value, and it's clearly the last use of that variable), what you get is 1. If the value can be moved, it's moved. 2. If the value can't be moved, but it can be copied, then it's copied. 3. If the value can't be moved or copied, then it's an error. Then in any situation where a copy is required, the type must support copying, or you get an error. And in any situation where moving is required, then the type must support moving, or it's an error. And in any situation where the compiler has to do a copy, but the programmer wants a move (e.g. because the programmer knows that it's actually the last use of the variable, but the compiler doesn't know enough to guarantee that), the programmer will have to use an explicit move (in which case, the variable is set to the init value in case the programmer got it wrong, which is what happens now). So, that way, the programmer can control for a given type whether copies or moves are done, and they'll get errors when the compiler can't make the code work with the operations that the type supports. Now, if you then have a type that's both copyable and moveable, and you want to guarantee that a particular place uses a move, you're pretty much forced to do an explicit move without us adding something akin to pragma(inline, ...) for moves, but you can still force it with an explicit move. Either way, I don't see why the callee would care whether a move had occurred or not. The function is given a value, and it operates on it. It's guaranteed to be owned by the function being called by virtue of the fact that it's not passed by ref. It's the caller that's going to care whether a move takes place, and that can be guaranteed by using an explicit move. - Jonathan M Davis
Jul 18
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 7/19/24 00:09, Jonathan M Davis wrote:
 Either way, I don't see why the callee would care whether a move had
 occurred or not. The function is given a value, and it operates on it. It's
 guaranteed to be owned by the function being called by virtue of the fact
 that it's not passed by ref. It's the caller that's going to care whether a
 move takes place, and that can be guaranteed by using an explicit move.
A primary use case would be forcing a move without the option of getting it wrong. I.e., the guaranteed move is a feature that the callee exposes to the caller. I really dislike `.init` for some use cases. This is just null pointers.
Jul 20
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 7/13/24 08:36, Richard (Rikki) Andrew Cattermole wrote:
 On 13/07/2024 7:46 AM, Walter Bright wrote:
 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1040.md

 We're going to get back on it.
We did some reading and reviewing of it last night. Some observations: 1. It could be simplified greatly if we had type state analysis (blit init over it and be done with it).
Not sure where `.init` enters the picture.
 2. Its acting in the form of an optimization, rather than trying to be 
 100% moves only feature.
Well, it has to be backwards-compatible, and it does enable move-only types to be used more conveniently.
 3. Isolated ala Midori could be used instead, and that buys us ownership 
 transfer for temporal safety.
I think this is orthogonal.
 4. The move constructor isn't great, it is too easily confused. It is 
 closely related to ``opAssign`` so ``opMove`` or ``opAssignMove`` might 
 be better candidates.
I think `this(S s){}` may be okay, but there should be explicit syntax to optionally elide the destructor call, so that the constructor does not leak anything by accident. By default, a user will most likely expect the destructor to be called, as there is nothing special about the syntax.
Jul 14
parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 14/07/2024 10:25 PM, Timon Gehr wrote:
 On 7/13/24 08:36, Richard (Rikki) Andrew Cattermole wrote:
 On 13/07/2024 7:46 AM, Walter Bright wrote:
 https://github.com/dlang/DIPs/blob/master/DIPs/DIP1040.md

 We're going to get back on it.
We did some reading and reviewing of it last night. Some observations: 1. It could be simplified greatly if we had type state analysis (blit init over it and be done with it).
Not sure where `.init` enters the picture.
The primary purpose is to keep the variable in a known good state. Cleanup and reassignment can occur safely.
 2. Its acting in the form of an optimization, rather than trying to be 
 100% moves only feature.
Well, it has to be backwards-compatible, and it does enable move-only types to be used more conveniently.
Right, but its only doing a move on the last transfer, optimizing the copy operation.
 3. Isolated ala Midori could be used instead, and that buys us 
 ownership transfer for temporal safety.
I think this is orthogonal.
Depends on what it is for. If its a way to describe transferring ownership of memory then isolated should work in almost all cases. Both within a function scope and between functions or graphs. If it is to help optimize your code then it is a success at that. D isn't C++, we don't blur the lines between classes and structs. What will fit best for us for ownership transfer won't be move constructors like C++ has.
Jul 14