On Wed, Jul 29, 2009 at 1:08 AM, Daniel Keep<[email protected]> wrote: > > > Jarrett Billingsley wrote: >> On Tue, Jul 28, 2009 at 10:33 PM, Walter >> Bright<[email protected]> wrote: >>> The issue is what if b is a property, returns a temporary object, and that >>> temp's .c field is uselessly set to 3? >> >> So, the issue is that 'a.b()' returns a struct by value. Such return >> values should always be considered rvalues. Furthermore, >> 'rvalue.field' should also only yield an rvalue. Therefore, 'a.b.c = >> 3' should be flagged by the compiler as being as nonsensical as "5 = >> x". >> >> The compiler would flag this as an error, and the solution would of >> course be to make a.b's return value by reference instead. > > Problem: what if .b is computed? Take .length as an example; the setter > MUST be invoked when the length changes, or the stored value won't have > any bearing on the actual number of elements being stored.
That's not the issue at hand. The issue is that the compiler accepts no-effect modifications of temporary values as valid statements. There is no setter being invoked here, nor should there be. Or should there? In the face of a value type, should the compiler rewrite this code as auto t = a.b(); t.c = 3; a.b = t; ? The last line of the rewrite is unnecessary if a.b() returns a reference type or a byref struct. But is this what people would expect to happen? > Returning refs only works if the property is just pretending to be a > field; in which case the correct solution is to use a field. Not entirely; you can (for some value of 'can') return a struct that has overloaded opAssign to do nontrivial setters. But that's kludgey and C++-y.
