Bug in compiler?

via Digitalmars-d digitalmars-d at puremagic.com
Mon Dec 15 07:00:54 PST 2014


On Monday, 15 December 2014 at 14:33:51 UTC, ketmar via 
Digitalmars-d wrote:
> On Mon, 15 Dec 2014 16:01:35 +0200
> Shachar Shemesh via Digitalmars-d <digitalmars-d at puremagic.com> 
> wrote:
>
>> Please consider the following program:
>> import std.exception;
>> 
>> void main()
>> {
>>      struct A {
>>          int a;
>> 
>>          @disable this(this);
>>          @disable ref A opAssign(const ref A);
>> 
>>          ref A opOpAssign(string op: "~")(int data) {
>>              a += data;
>> 
>>              return this;
>>          }
>>      }
>> 
>>      auto a = A(2);
>> 
>>      a ~= 3;
>> 
>>      assertThrown!Exception(a ~= 3);
>> }
>> 
>> Compilation (dmd 2.066.1) fails on the assertThrown line:
>> Error: struct test.main.A is not copyable because it is 
>> annotated with @disable
>> 
>> What I do not understand is why A should need to be copyable. 
>> Where is the copy made? I'm guessing this is because of the 
>> lazy definition of the expression, but still I don't see any 
>> reason to create a copy.
>
> yes, this is due to `lazy` in assrtThrown. what `lazy` does is 
> actually
> creating a lambda. then compiler tries to deduce the type of the
> expression and it got `A`. so it generates the code like
> `A expression`. it can't see `ref` there, as `a` type is `A`, 
> not
> `ref A`.
>
> you can workaround that with creating the necessary lambda 
> manually:
>
>   assertThrown!Exception((ref A aa) { aa ~= 3; }(a));
>
>
> tl;dr: no, it's not a bug in the compiler. but the error 
> message is
> misleading and you are required to understang some internals to 
> make
> sense out of it.

Another point against storage class ref.


More information about the Digitalmars-d mailing list