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.