diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index ef6c1bd0793..aba99556ad8 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -3280,9 +3280,10 @@ private bool functionParameters(const ref Loc loc, Scope* sc, } else if (p.storageClass & STC.ref_) { + FuncDeclaration f; if (global.params.rvalueRefParam == FeatureState.enabled && !arg.isLvalue() && - targ.isCopyable()) + targ.isCopyable(f)) { /* allow rvalues to be passed to ref parameters by copying * them to a temp, then pass the temp as the argument */ @@ -12253,7 +12254,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } if (tb1.ty == Tpointer && tb2.ty == Tpointer || - tb1.ty == Tnull && tb2.ty == Tnull) + tb1.ty == Tnull && tb2.ty == Tnull) { result = exp.incompatibleTypes(); return; diff --git a/compiler/src/dmd/traits.d b/compiler/src/dmd/traits.d index e065975c67a..8e0b147038b 100644 --- a/compiler/src/dmd/traits.d +++ b/compiler/src/dmd/traits.d @@ -588,7 +588,8 @@ Expression semanticTraits(TraitsExp e, Scope* sc) ts.sym.dsymbolSemantic(sc); } - return isCopyable(t) ? True() : False(); + FuncDeclaration f; + return isCopyable(t, f) ? True() : False(); } if (e.ident == Id.isNested) diff --git a/compiler/src/dmd/typesem.d b/compiler/src/dmd/typesem.d index f947dd33174..de0856fc388 100644 --- a/compiler/src/dmd/typesem.d +++ b/compiler/src/dmd/typesem.d @@ -437,10 +437,11 @@ private Dsymbol searchX(Dsymbol dsym, const ref Loc loc, Scope* sc, RootObject i * Determine if type t is copyable. * Params: * t = type to check + * f = set to constructor that would be called, if any * Returns: * true if we can copy it */ -bool isCopyable(Type t) +bool isCopyable(Type t, out FuncDeclaration f) { //printf("isCopyable() %s\n", t.toChars()); if (auto ts = t.isTypeStruct()) @@ -458,7 +459,7 @@ bool isCopyable(Type t) el.type = cast() ts; Expressions* args = new Expressions(); args.push(el); - FuncDeclaration f = resolveFuncCall(Loc.initial, null, ctor, null, cast()ts, ArgumentList(args), FuncResolveFlag.quiet); + f = resolveFuncCall(Loc.initial, null, ctor, null, cast()ts, ArgumentList(args), FuncResolveFlag.quiet); if (!f || f.storage_class & STC.disable) return false; } @@ -882,14 +883,35 @@ extern (D) MATCH callMatch(TypeFunction tf, Type tthis, ArgumentList argumentLis private extern(D) bool isCopyConstructorCallable (StructDeclaration argStruct, Expression arg, Type tprm, Scope* sc, const(char)** pMessage) { + //printf("isCopyConstructible()\n"); + FuncDeclaration f; + + bool b1 = isCopyable(argStruct.type, f); + auto tmp = new VarDeclaration(arg.loc, tprm, Identifier.generateId("__copytmp"), null); tmp.storage_class = STC.rvalue | STC.temp | STC.ctfe; tmp.dsymbolSemantic(sc); Expression ve = new VarExp(arg.loc, tmp); - Expression e = new DotIdExp(arg.loc, ve, Id.ctor); - e = new CallExp(arg.loc, e, arg); + Expression ex = new DotIdExp(arg.loc, ve, Id.ctor); + Expression e = new CallExp(arg.loc, ex, arg); //printf("e = %s\n", e.toChars()); - if (dmd.expressionsem.trySemantic(e, sc)) + + bool b2 = dmd.expressionsem.trySemantic(e, sc) !is null; + + if (b1 != b2) + { + fprintf(stderr, "b1: %d b2: %d\n", b1, b2); + fprintf(stderr, "argStruct.type: %s\n", toChars(argStruct.type)); + fprintf(stderr, "arg: %s\n", arg.toChars()); + fprintf(stderr, "arg.type: %s\n", toChars(arg.type)); + fprintf(stderr, "tprm: %s\n", toChars(tprm)); + fprintf(stderr, "ex: %s\n", ex.toChars()); + fprintf(stderr, "e: %s\n", e.toChars()); + fprintf(stderr, "e.type: %s\n", toChars(e.type)); + if (f) + fprintf(stderr, "f: %s\n", toChars(f.type)); + } + if (b1) return true; if (!pMessage) @@ -904,7 +926,7 @@ private extern(D) bool isCopyConstructorCallable (StructDeclaration argStruct, * such as purity, safety or nogc. */ OutBuffer buf; - auto callExp = e.isCallExp(); +// auto callExp = e.isCallExp(); bool nocpctor() { @@ -914,7 +936,7 @@ private extern(D) bool isCopyConstructorCallable (StructDeclaration argStruct, return false; } - auto f = callExp.f; +// auto f = callExp.f; if (!f) return nocpctor(); @@ -1043,6 +1065,7 @@ private extern(D) MATCH argumentMatchParameter (TypeFunction tf, Parameter p, return MATCH.nomatch; } + FuncDeclaration f; if (arg.op == EXP.string_ && tp.ty == Tsarray) { if (ta.ty != Tsarray) @@ -1077,7 +1100,7 @@ private extern(D) MATCH argumentMatchParameter (TypeFunction tf, Parameter p, } else if (global.params.rvalueRefParam != FeatureState.enabled || p.storageClass & STC.out_ || - !arg.type.isCopyable()) // can't copy to temp for ref parameter + !arg.type.isCopyable(f)) // can't copy to temp for ref parameter { if (pMessage) *pMessage = tf.getParamError(arg, p); return MATCH.nomatch; diff --git a/compiler/test/compilable/test23097.d b/compiler/test/compilable/test23097.d index 092bd774f22..4610b5fd6b7 100644 --- a/compiler/test/compilable/test23097.d +++ b/compiler/test/compilable/test23097.d @@ -2,11 +2,7 @@ REQUIRED_ARGS: -verrors=spec TEST_OUTPUT: --- -(spec:2) compilable/test23097.d(14): Error: `inout` constructor `test23097.S23097.this` creates const object, not mutable -(spec:2) compilable/test23097.d(14): Error: `inout` constructor `test23097.S23097.this` creates const object, not mutable -(spec:1) compilable/test23097.d(14): Error: generated function `test23097.S23097.opAssign(S23097 p)` is not callable using argument types `(const(S23097))` -(spec:2) compilable/test23097.d(14): Error: `inout` constructor `test23097.S23097.this` creates const object, not mutable -(spec:1) compilable/test23097.d(14): `struct S23097` does not define a copy constructor for `const(S23097)` to `S23097` copies +(spec:1) compilable/test23097.d(10): Error: `inout` constructor `test23097.S23097.this` creates const object, not mutable --- */ void emplaceRef(UT, Args)(UT chunk, Args args) diff --git a/compiler/test/fail_compilation/fail22202.d b/compiler/test/fail_compilation/fail22202.d index 9fb5165a711..7932af4b7eb 100644 --- a/compiler/test/fail_compilation/fail22202.d +++ b/compiler/test/fail_compilation/fail22202.d @@ -3,9 +3,10 @@ /* TEST_OUTPUT: --- -fail_compilation/fail22202.d(22): Error: function `fun` is not callable using argument types `(SystemCopy)` -fail_compilation/fail22202.d(22): `inout ref inout(SystemCopy)(ref inout(SystemCopy) other)` copy constructor cannot be called from a `pure @safe nogc` context -fail_compilation/fail22202.d(17): `fail22202.fun(SystemCopy __param_0)` declared here +fail_compilation/fail22202.d(23): Error: `pure` function `D main` cannot call impure copy constructor `fail22202.SystemCopy.this` +fail_compilation/fail22202.d(23): Error: `@safe` function `D main` cannot call `@system` copy constructor `fail22202.SystemCopy.this` +fail_compilation/fail22202.d(15): `fail22202.SystemCopy.this` is declared here +fail_compilation/fail22202.d(23): Error: `@nogc` function `D main` cannot call non-@nogc copy constructor `fail22202.SystemCopy.this` --- */