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