Bug in compiler?

John Colvin via Digitalmars-d digitalmars-d at puremagic.com
Mon Dec 15 07:02:47 PST 2014


On Monday, 15 December 2014 at 15:00:56 UTC, Marc Schütz wrote:
> 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.

Perhaps. I would say lazy should be clever enough to work this 
out.


More information about the Digitalmars-d mailing list