July 15
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.
July 16

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?

July 17
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.)
July 17

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.

July 18
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.

July 19
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.
July 18
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.
July 18
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



July 20
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.
1 2
Next ›   Last »