This is the feedback thread for the first round of Community
Review of DIP 1040, "Copying, Moving, and Forwarding".
I'm really late to the party here, and there's a lot to catch up, so maybe I'm repeating discussion that already happened... but I think there's a few points that need consideration.
First, I like this DIP, I think this is good for D. That said, I also care deeply about C++ compatibility, and this DIP introduces some serious issues.
1. This changes the extern(C++) ABI, and it's a major breaking change, yet it's not mentioned in the breaking changes section; every by-val constructor call will have an ABI change, and C++ compatibility will completely explode.
2. By-val declarations matching f(T&&) is not a great default. It's relatively uncommon in C++ for these arguments to exist unless it makes specific sense, and many cases where it is present C++ uses 'universal references', that infer rval-ness.
3. ...and even when they do exist, this DIP has different ABI semantics! The C++ `T&&` function still expects the caller to destruct the argument, but in D, the caller will never destruct a moved argument. You talk about this, saying that it's a requirement to pay special attention to the semantic difference, but I don't think that's reasonable. You're going to have endless reports of issues from people that don't read or don't *understand* the difference, and complain their program is crashing.
4. Is it that C++'s criteria for an EMO matches your definition, or will there emerge cases where a differing EMO assessment will produce a mismatch in calling convention?
I think there are more problems I can imagine if I dive into the weeds, but at least these need to be addressed in the DIP.
My off-the-cuff thoughts are:
1 & 2. Rather than applying EMO semantics to extern(C++) functions by default, and using @value to nominate the default behaviour; since you've accepted an attribute just for C++ disambiguation, why not assume by-val semantics as default, and require an @rval-ref attribute instead to select the C++ move ABI?
3. Since your EMO semantics don't actually apply to C++, that is, destruction responsibility does NOT carry into the call, I don't think EMO semantics as described actually apply to C++ at all, and shouldn't be attempted. We should use a separate solution for C++ compat (like the attribute I mention above) and EMO semantics have no impact on C++.
So, in the presence of extern(C++), f(T arg) behaves 'traditionally' (as you describe when applying `@value`), and maybe something like f(T @rvalref arg) introduces the C++ rules (together with some attention to overloading). EMO semantics as described have no applicability to C++.
Your C++ compatibility section needs a complete do-over as far as I'm concerned. They don't improve the situation for C++ compatibility, they make it worse.
Perhaps it should be tackled as a separate matter, and in that event, I think the simplest thing to do is to assume f(T) for EMO remains by-val for extern(C++), that is "EMO calling only applies to extern(D) code", and then we make an @rvalref attribute that applies only to extern(C++) for the sake of matching calling convention in a future DIP?
I might be interested in attempting a DIP that adds an extern(C++)-only rval-ref attribute on top of this DIP; It needs more work. Existing work (for instance, last SAOC) was taken from the perspective that it solves move semantics in D at the same time as interfacing C++. With this DIP addressing elaborate move in D, I think a new approach which ONLY addresses interfacing C++ is an easier sell, and keeps the feature much more isolated.