On Sunday, 30 September 2012 at 00:24:34 UTC, Ali Çehreli wrote:
On 09/29/2012 04:02 PM, Timon Gehr wrote:
> On 09/30/2012 12:51 AM, Ali Çehreli wrote:
>> On 09/29/2012 11:16 AM, Timon Gehr wrote:
>> > On 09/29/2012 06:26 PM, Maxim Fomin wrote:
>>
>> >>> S s = S(1,2,3);
>> >>> s = S(4, s.a, 6);
>> >>>
>> >>> assert(a == [4,1,6]);
>> >>> assert(s == S(4,4,6));
>> >>> }
>> >>>
>> >>> Setting the struct writes s.a before evaluating it while
the reverse
>> >>> is true of the array assignment. Using DMD 2.0.60. GDC
does what I'd
>> >>> expect and gives both as 4,1,6.
>> >>
>> >> I think this is notorious "i = ++i + ++i".
>> >
>> > There is only one mutating sub-expression.
>>
>> But that mutation is happening to an object that is also
being read
>> inside the same expression.
>>
>> This is one of the definitions of undefined behavior, not a
compiler bug.
>>
>> >> Statement s = S(4, s.a, 6) writes to s object and
simultaneously reads
>> >> it.
>> >> http://dlang.org/expression.html states that assign
expression is
>> >> evaluated in implementation defined-manner and it is an
error to
>> depend
>> >> on things like this.
>> >
>> > No evaluation order of the assignment expression can
possibly lead to
>> > this result. This seems to be a DMD bug.
>>
>> The compiler seems to be applying an optimization, which it
is entitled
>> to as long as the language definition is not violated.
>>
>
> Technically there is no language definition to violate.
>
>> If we are using the same object both to read and write in
the same
>> expression, then we should expect the consequences.
>>
>
> No. Why?

I am confused. Of course single mutation and many reads should be fine.

>
>> Disclaimer: I assume that D's rules are the same as C and
C++ here.
>>
>
> C and C++ do not have struct literals and if I am not
mistaken,
> constructor invocation is a sequence point.

Yes. And in this case it is the compiler-generated constructor. The OP's problem goes away if there is a user-provided constructor:

    struct S {
        int a, b, c;

        this(int a, int b, int c)
        {
            this.a = a;
            this.b = b;
            this.c = c;
        }
    }

Now it is as expected:

    assert(s == S(4,1,6));

> Besides, this does not make any sense, what is the relevant
part of the
> standard?
>
> int c = 0;
> c = c+1; // c is both read and written to in the same
expression

Silly me! :p

Ali

This would still seem to be a very poor behaviour worth fixing. What is the compiler generating instead of the constructor example you gave?

Reply via email to