| Thread overview | ||||||
|---|---|---|---|---|---|---|
|
December 15, 2014 Bug in compiler? | ||||
|---|---|---|---|---|
| ||||
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.
Help?
Shachar
| ||||
December 15, 2014 Re: Bug in compiler? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Shachar Shemesh Attachments: | On Mon, 15 Dec 2014 16:01:35 +0200
Shachar Shemesh via Digitalmars-d <digitalmars-d@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.
| |||
December 15, 2014 Re: Bug in compiler? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to ketmar | 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@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.
| |||
December 15, 2014 Re: Bug in compiler? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Marc Schütz | 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@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.
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply