5 days ago
On 01/10/2024 4:11 PM, Walter Bright wrote:
> On 9/30/2024 1:28 PM, Richard (Rikki) Andrew Cattermole wrote:
>> 1. Nobody has been able to answer what the purpose of them is
> 
> Performance.

Ah huh!

Now I'm on board with us having move constructors.

5 days ago
On 9/30/2024 10:49 AM, Dukc wrote:
> Doesn't `core.lifetime.move` already do this?

Since the compiler doesn't know about it, the potential for optimizations, lifetime analysis, etc., is lost.
5 days ago
On 01/10/2024 4:22 PM, Walter Bright wrote:
> On 9/30/2024 10:49 AM, Dukc wrote:
>> Doesn't `core.lifetime.move` already do this?
> 
> Since the compiler doesn't know about it, the potential for optimizations, lifetime analysis, etc., is lost.

If only there was a way that was backwards compatible, for us to annotate on a parameter that it invalidates the input in the form of a move.

Perhaps an attribute, like ``@move`` in core.attributes would be sufficient for this task ;)

5 days ago
On 9/30/2024 10:27 AM, Bastiaan Veelo wrote:
> I suppose `-preview=rvaluerefparam` is not relevant here, right?

It should be irrelevant here.

5 days ago

On Monday, 30 September 2024 at 19:37:04 UTC, Timon Gehr wrote:

>

Otherwise, maybe expose explicit moves. This is useful generally. Can just be move(x), where move is either special, or is a function with a "move by default" attribute on its parameter, as we discussed previously.

Considering the template-complexity of the current implementation of core.lifetime.move it will beneficial compile-time wise to make move become a builtin. Ideally I would like to have a special syntax for converting an l-value to an r-value.

5 days ago
On 9/30/2024 8:29 PM, Richard (Rikki) Andrew Cattermole wrote:
> Perhaps an attribute, like ``@move`` in core.attributes would be sufficient for this task ;)


It's an interesting idea, but a lot of details would need to be worked out. For instance, the core.attributes.move is a version of the move assignment operator, not move construction. Then there is the problem of distinguishing between a move constructor and a copy constructor - how do they overload against each other? There's what a default move constructor should be. There's what happens when a field of a struct has a move constructor.

And so on.

BTW, I took a look at core.lifetime.move. It's hard to figure out just what it does, as there are vacuous forwardings to other templates.

For example:
```
void move(T)(ref T source, ref T target)
{
    moveImpl(target, source);
}
```
Why?

5 days ago
On 9/30/2024 9:55 PM, Per Nordlöw wrote:
> Ideally I would like to have a special syntax for converting an l-value to an r-value.

Manu suggested an intrinsic, something like:

```
__rvalue(s)
```
where __rvalue is a keyword.

5 days ago

On Tuesday, 1 October 2024 at 03:22:33 UTC, Walter Bright wrote:

>

On 9/30/2024 10:49 AM, Dukc wrote:

>

Doesn't core.lifetime.move already do this?

Since the compiler doesn't know about it, the potential for optimizations, lifetime analysis, etc., is lost.

You can make it to work with a compiler instrinsic. The intrinsic would either be an UDA applied to move that allows the compiler to make those assumptions, or an intrinsic function that works along the lines of nove and moveEmplace. The public DRuntime functions would forward or alias to the instrinsic function.

5 days ago

On Tuesday, 1 October 2024 at 04:55:43 UTC, Per Nordlöw wrote:

>

Ideally I would like to have a special syntax for converting an l-value to an r-value.

Why special syntax? move is a DRuntime function so it's expected that it can have special semantics, even without special syntax.

5 days ago
On 01/10/2024 7:36 PM, Walter Bright wrote:
> On 9/30/2024 8:29 PM, Richard (Rikki) Andrew Cattermole wrote:
>> Perhaps an attribute, like ``@move`` in core.attributes would be sufficient for this task ;)
> 
> 
> It's an interesting idea, but a lot of details would need to be worked out. For instance, the core.attributes.move is a version of the move assignment operator, not move construction.

Yes!

> Then there is the problem of distinguishing between a move constructor and a copy constructor - how do they overload against each other?

Why do you need to?

Are they not the same constructor, differing only for the side effects to the caller?

It is an assumption that the object you pass in by-ref will be the same object after the function call.

```d
int* someObject = ...;

int* obj = someObject;
callMe(obj);

// Does obj == someObject?
```

If you know that ``callMe`` moved the value into it, but never assigned to it, you can elide cleanup on ``obj``.

A question I ask myself in any sort of proving topics is what assumptions are being held, and can under normal usage of ``@safe`` code can these assumptions be invalidated, potentially desirably.

I had a look at C++, it seems the biggest difference between a copy constructor and a move constructor is that a move constructor is mutable by-ref, whereas a copy is read only. Which could indeed be overloaded for in D.

And yes, we could infer the difference in this regards in D too. It is what I have been calling "effectively-const". A rather useful thing for owner escape analysis, as it means methods on the owner that do not mutate are callable even if they cannot or have not been annotated ``const``!