| |
 | Posted by Jonathan M Davis in reply to partypooper | Permalink Reply |
|
Jonathan M Davis 
Posted in reply to partypooper
| On Friday, July 4, 2025 12:04:55 PM Mountain Daylight Time partypooper via Digitalmars-d-learn wrote:
> On Friday, 4 July 2025 at 17:34:59 UTC, monkyyy wrote:
> > On Friday, 4 July 2025 at 17:15:48 UTC, partypooper wrote:
> > if you add ref to line 28 it works; there wont be a reasonable
> > way to make an error happen, you just have to know when to do
> > refness
>
> It doesn't work. Or it works even worse: changing _pos, but not _dest. What is going on is that on `+=` it for some reason invokes "getter", not "setter". I specifically omitted "ref", because I already have known of that behavior.
The only time that a setter function would be triggered would be assignment such as
a.pos = foo;
+= is not assignment. Sure, conceptually, you're adding two values together and then assigning the result, but in practice, it's just a function call, and that function call is opOpAssign!"+".
So, in order for the compiler to use += on a property in the way that you're attempting, all it can do is get the value with the getter and then call opOpAssign!"+" on it. In order to use the setter, it would need to break the operation up into + and = so that it could use the getter with + and the setter with =, but that's not how overloaded operators work. Technically, as far as the language is concerned, += is unrelated to + or =. It's its own thing.
The only way that I see that this could work would be if the language
mandated that a += b; was equivalent to a = a + b; _and_ that the compiler
was allowed to turn a += b; into a = a + b; Obviously, if a += b; and
a = a + b; aren't logically equivalent, then the overloaded operator is to
overloading these operators in an appropriate way, but I don't think that
the language actually has any requirement that there's any equivalent, and
it certainly doesn't allow the compiler to transform one into the other.
So, making it so that the compiler is allowed to do such a transformation would require change to the language (presumably by going through the DIP process). I don't know how likely that is, but it may happen, since some folks do want to make it so that property functions are able to do more.
That being said, as things stand, this really should be an error, and if you use built-in types, it is. E.G.
void main ()
{
S s;
s.prop += 42;
}
struct S
{
int i;
int prop() { return i; }
void prop(int i) { this.i = i; }
}
will give
q.d(4): Error: cannot modify expression `s.prop()` because it is not an
lvalue
s.prop += 42;
^
Unfortunately though, the compiler does not have that restriction when opOpAssign is overloaded. There is an open bug report for it, but it doesn't seem to have been a high enough priority for anyone to fix it yet:
https://github.com/dlang/dmd/issues/19061
So, hopefully it gets fixed at some point here, but for now, we're kind of stuck, and you'll need unit tests to catch the cases where you accidentally do some form of assignment on an rvalue when overloaded operators are involved.
- Jonathan M Davis
|