On Sat, 12 Oct 2024 at 03:18, Jonathan M Davis via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
On Friday, October 11, 2024 9:19:54 AM MDT Manu via Digitalmars-d wrote:
> The move semantic described by the dip should apply to every rvalue
> everywhere; they're all potential move targets.
>
> Especially so for your weird
> not-a-move-constructor-but-actually-a-move-constructor that receives T by
> value; it's the exact definition of a move constructor, and it should be
> the case that concretely proves that it is also the exact proper syntax for
> the declaration!

Just because a constructor such as this(typeof(this)) looks like a move
constructor doesn't guarantee that it has those semantics.

It doesn't matter whether it does or doesn't... what the function does is irrelevant. It's just a function call which can receive a particular category of argument (r-values) more efficiently than the existing code.
We're really hung up on move constructors, but this DIP is really about "move semantics", which of course have something to do with move constructors, but move semantics are so much more than a constructor.

We have no clue
what the programmer chose to do in that case given that it is not currently
used as a move constructor and there was zero expectation that it ever would
be.

That's fine, it's welcome to discard the value, nobody's judging. It's still a constructor, so it must initialise an instance of some kind, and it only accepts an r-values, so it's something like a move constructor, whatever it does.

While the obvious use case is to construct the new object with the same
value as the original, we cannot guarantee that that is what the programmer
actually did. They could have simply chosen to take parts of the original
and not the entire thing, using that constructor as a way to pass specific
parts of the object's state but not all of it, whereas with a move, they
would want the object to be moved exactly as-is.

I'm getting the impression that you don't really know much about move semantics. I get the feeling you've made a lot of assumptions which are all mostly wrong :/

Right now, the programmer
can rely on that constructor only being called when they've explicitly
called it, and they're free to do whatever they want with it even if plenty
of other folks would think that what they did was a bad idea. Changing it so
that that constructor suddenly got called implicitly in a bunch of cases
would potentially break their code -

Wait... what? Why wouldn't that constructor be callable implicitly?

I can do this:
struct S {
  this(int) {}
}
S s = 10;

That calls an arbitrary constructor implicitly... why is your case something different?

Can you show any example to your point? I can't imagine it. I think it's time we understand how this hypothetical thing might get called...?


as well as likely hurting performance,
since they were presumably fine with the move semantics that they had
previously and didn't want their constructor called in those cases.

Okay, so I think I see your hypothetical case now; some implicitly generated move might just blit and not call their function? (specifically because the function is not blessed, and so some internal compiler generated thing takes precedence?
This is actually THE EXACT REASON I've given for criticising the idea of blessing special functions... edge cases, edge cases everywhere! People lean into weird edge cases, often when they don't even intend to or understand that they have. The language is super non-uniform and full of nooks and crannies where "weird shit" hang out.

Anyway, I don't think this thing actually exists; even though it's hypothetically possible, it just doesn't make sense, and it would be brittle as hell because the compiler would select between its own thing and the explicitly written thing based on whatever situational takes precedent.
You'll need to show us some cases... if the cases are legit, and not actually just bugs in random user code, then we can study them.


Another issue here is the refness of the parameter. Move constructors really
should be taking their argument by ref, not by value, since it's not being
copied, and it hasn't been moved yet. However, for better or worse,
this(ref typeof(this)) is already a copy constructor. Having a separate
syntax for move constructors allows us to have it be =this(ref typeof(this))
or @move this(ref typeof(this)) or whatever, and then it's distinct from
copy constructors while still having ref like it really should.
Using this(typeof(this)) while implicitly treating the parameter as ref even
though it isn't just creates a needless special case.

This repeats and highlights what I said in my post on the other thread...