Issue 1974 - What's your opinion?
John Colvin
john.loughran.colvin at gmail.com
Sat Oct 26 14:41:38 UTC 2019
On Thursday, 24 October 2019 at 08:02:28 UTC, RazvanN wrote:
> Hello everyone,
>
> I am currently trying to solve old issues but some of them I'm
> not entirely sure how to handle. One of them is 1974 [1].
> Here's the thing:
>
> struct Foo { int y; void opAddAssign(int z) { y += z; } }
> struct Bar { Foo fou; Foo test() { return fou; } }
> void main() {
> Bar x;
> x.fou.y = 0;
> x.test() += 1337;
> writefln(x.fou.y);
> }
>
> The problem is that x.test() += 1337; calls opAddAssign on a
> temporary and the person that filed the bug report claimed that
> this should be an error since the call is useless (in this
> case).
>
> I have responded to the issue with the following:
>
> "This is a bit problematic because there are 2 points of view
> on this:
>
> 1. From a high-level point of view, the bug report is valid,
> you are trying to assign to an rvalue (x.test() = x.test() +
> 1337) which should an error.
>
> 2. From a lowering point of view you are basically calling the
> member function of a temporary object
> (x.test.opAddAssign(1337)), which by the current rules is valid
> behavior.
>
> I guess that what could be implemented is something along the
> lines of: if the opAssign/op*Assign function is pure, then you
> can error/warn because the call has no effect, otherwise it is
> possible that the assign function has side effects so calling
> it is correct."
>
> What are your thoughts on this? Should be close the issue as an
> invalid one?
>
> Cheers,
> RazvanN
>
> [1] https://issues.dlang.org/show_bug.cgi?id=1974
I think the lowering is a distraction.
+= on an rvalue is invalid, so the lowering should never happen.
The implementation of operator overloads may be done with regular
functions, but the "interface" of += doesn't make sense on an
rvalue. If you want to call your opOpAssign on an rvalue, that's
fine, but that's not the same as +=
If you want to stick with thinking/implementing by lowering, you
could do something like this (for structs at least):
auto ref __opOpAssignImpl(string op, S, T)(ref S s, auto ref T s)
{
return s.opOpAssign!op(forward!s);
}
and then a+=b is lowered to a.__opOpAssignImpl(b) and if a is an
rvalue you will get your error.
More information about the Digitalmars-d
mailing list