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
<[email protected]> 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.