string result; struct A { this(ref A rhs) { result ~= "A"; } this(ref immutable A rhs) { result ~= "B"; } this(ref const A rhs) { result ~= "C"; } this(ref A rhs) immutable { result ~= "D"; } this(ref const A rhs) shared { result ~= "E"; } this(ref A rhs) shared { result ~= "F"; } this(ref shared A rhs) immutable { result ~= "G"; } this(ref shared A rhs) shared { result ~= "H"; } } // copy constructor correctly uses function declaration overload resolution void test1() { result = ""; A a; A a1 = a; immutable A a2 = a; const A a3 = a2; shared A a4 = a3; A a5 = a3; assert(result == "ADBEC"); } // copy constructor has priority over alias this struct B { B fun(immutable B) { return B(); } this(ref immutable B rhs) { result ~= "A"; } alias fun this; } void test2() { result = ""; immutable B a; B a1 = a; assert(result == "A"); } // arguments and return values correctly call the copy constructor shared(A) fun(A x) { return x; } immutable(A) fun2(shared A x) { return x; } void test3() { result = ""; A a1; shared A a2 = fun(a1); immutable A a3 = fun2(a2); assert(result == "AFHG"); } // nested structs int fun() { int x = 1; struct A { struct B { int x2 = 2; } B b; int x1; this(int x) { this.x1 = x; b = B(3); } this(ref A rhs) { this.x1 = rhs.x1 + rhs.b.x2 + x; } } A a = A(2); A b = a; return b.x1; } void test4() { assert(fun() == 6); } // generated copy constructor struct X { this(ref inout(X) rhs) inout { result ~= "A"; } } struct Y { X a; } void test5() { result = ""; Y b1; Y b2 = b1; assert(result == "A"); } void main() { test1(); test2(); test3(); test4(); test5(); }