diff --git a/src/core/internal/traits.d b/src/core/internal/traits.d index 80139415bd..60194a40c4 100644 --- a/src/core/internal/traits.d +++ b/src/core/internal/traits.d @@ -258,7 +258,33 @@ template hasElaborateCopyConstructor(S) } else static if (is(S == struct)) { - enum hasElaborateCopyConstructor = __traits(hasMember, S, "__xpostblit"); + static if (__traits(hasMember, S, "__xpostblit")) + { + enum hasElaborateCopyConstructor = !__traits(isDisabled, S.__xpostblit); + } + else + { + enum hasElaborateCopyConstructor = () { + static if (__traits(hasMember, S, "__ctor")) + { + static foreach (f; __traits(getOverloads, S, "__ctor")) + {{ + bool r = __traits(compiles, { + auto p = &f; + + // Check if ctor is callable with lval or rval + S s = S.init; + (*p)(s); + + // Check that ctor is't callable with rval + static assert (!__traits(compiles, (*p)(S()) )); + }); + if (r) return true; + }} + } + return false; + }(); + } } else { @@ -266,6 +292,43 @@ template hasElaborateCopyConstructor(S) } } +@safe unittest +{ + struct S + { + int x; + this(return scope ref typeof(this) rhs) { } + this(int x, int y) {} + } + + static assert(hasElaborateCopyConstructor!S); + + struct S2 + { + int x; + this(int x, int y) {} + } + + static assert(!hasElaborateCopyConstructor!S2); + + struct S3 + { + int x; + this(return scope ref typeof(this) rhs, int x = 42) { } + this(int x, int y) {} + } + + static assert(hasElaborateCopyConstructor!S3); + + struct S4 + { + int x; + @disable this(this); + } + + static assert(!hasElaborateCopyConstructor!S4); +} + template hasElaborateAssign(S) { static if (__traits(isStaticArray, S) && S.length)