On 10/11/2024 12:06 AM, Manu wrote:
> If the overload resolution rules don't prefer an exact match over a conversion,
> then something is very wrong with the overload selection rules. What situations
> cause those waters to become murky?
The difference between an rvalue and lvalue is murky, for one. For example,
1. rvalues can be passed by ref under the hood, even though there's no `ref`
The semantic distinction in the front-end motivates the overload selection, not the calling convention.
lvalues and rvalues are absolutely distinct in language terms. Yes, they're both ref under the hood, that's irrelevant for overload selection. That's a codegen matter.
2. lvalues can match both a ref and a non-ref parameter
So can rvalues, and that's proper and perfectly normal. This is why overload resolution prefers exact-match.
3. rvalues can implicitly convert to lvalues with -preview=rvaluerefparam
Again, perfectly cool and normal, and why exact-match is the highest precedence selection criteria.
4. rvalue constructors exist and are used, and are NOT move constructors
They are rvalue constructors; it doesn't matter what they do, their selection criteria remains identical.
I could similarly write your a copy constructors that doesn't make a copy... that's my prerogative.
How could their selection semantics change?
> The fact you're talking about a separate constructor type to identify the move
> case leads me to suspect that the rvalue semantic only applies to the argument
> to that particular function and nothing else?
It's that rvalue constructors already exist and are in use.
Now they will receive their rvalues more efficiently.
Again, what change in the selection semantics exists here?
> That's not really "move semantics", that's just a move constructor... and I
> think I've completely misunderstood your DIP if this is correct?
You understood the DIP. I did not - it's unimplementable as it stands because of
the existing semantics.
I know this is sounding repetitive, but please be specific. Which existing semantics are in conflict?
We need case studies. This is too important to do wavy-hand stuff.
Yes, I'm extremely impressed with your design! Let's nail it. Don't butcher your best work!
This is the ultimate form of that zen-master perfect engineering, where the answer looks so simple that anyone could have thought of it... This actually moves a bar in the scope of the broader PL landscape. People will notice this.
> I have no way to know or assess whether any of the arrangements of rules you
> considered or tried actually arrange into a nice tight lattice or not... or if
> they were generally cohesive and well-formed. We're expected to accept that you
> tried every possible reasonable arrangement and conclusively determined that
> it's not workable. I have no idea how we can assess that for reality or not... :/
You're starting from a blank sheet of paper. I'm trying to fit it into the
existing semantics without breaking existing semantics and complicated user code.
Then enumerate the road blocks, bring each one to their own thread, and we can systematically work through them one by one.
If it's that rvalue constructors might exist and don't create a copy, then show that's actually true, and we can study if that's actually a thing which has a purpose... it's probably a bug in user code, or the function is actually a move constructor already.
We need to understand that case.
Have you found any other such problems? The other stuff you mentioned were implementation challenges, and certainly not showstoppers by any means.
D is a complicated language, and lots of people write stuff that doesn't actually work or make sense. It's easy to make something compile that doesn't actually work. We need to study the breakages and see if we're doing real harm... if the code is already a bug, then don't stress about it.
I think it's important to hold the importance of this in perspective; this is the single biggest massive gaping hole in the foundation of D. A large number of issues and edgy shit stems from this. Look at core.lifetime for evidence. This work will eliminate that entire dumpster fire, and round out the language in a seriously innovative and class-leading way.
This is NOT something you make trivial compromises and hacks with; value ownership and lifetime is the core-est, most fundamental shit that a language does, and edge-ey hacks are completely inappropriate at this level of the language.
Your design is remarkably (surprisingly!) compatible and non-destructive. I reckon you're not going to achieve perfect-non-breakage, why would you even imagine that's possible? This is way too deep and fundamental to assume that's a realistic goal.
We need to convince that the value outweighs the harm, which won't be hard; everyone wants this, even if they don't understand that.
...and that said, we have identified just one single oddity so far, and that oddity may be a red herring (because it's actually a move constructor in waiting), or maybe it's something that really doesn't make sense... What kind of constructor could accept only a self-type as argument, and then initialise an instance but not respect the source material, AND assert that that's the only possible way to express this nonsensicle concept?
We need to assess this case beyond the hypothetical, because if that's all we stand to break, we're in agonisingly good shape.