Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

isCopyConstructable should call isCopyable #16944

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions compiler/src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dmd/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
39 changes: 31 additions & 8 deletions compiler/src/dmd/typesem.d
Original file line number Diff line number Diff line change
Expand Up @@ -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)
thewilsonator marked this conversation as resolved.
Show resolved Hide resolved
{
//printf("isCopyable() %s\n", t.toChars());
if (auto ts = t.isTypeStruct())
Expand All @@ -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;
}
Expand Down Expand Up @@ -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)
Expand All @@ -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()
{
Expand All @@ -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();

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 1 addition & 5 deletions compiler/test/compilable/test23097.d
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
7 changes: 4 additions & 3 deletions compiler/test/fail_compilation/fail22202.d
Original file line number Diff line number Diff line change
Expand Up @@ -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`
---
*/

Expand Down
Loading