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.

Reply via email to