Skip to content
Merged
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
25 changes: 12 additions & 13 deletions src/dmd/mtype.d
Original file line number Diff line number Diff line change
Expand Up @@ -4780,19 +4780,20 @@ extern (C++) final class TypeFunction : TypeNext
}

// arguments get specially formatted
private const(char)* getParamError(const(char)* format, Expression arg, Parameter par)
private const(char)* getParamError(Expression arg, Parameter par)
{
// show qualification when toChars() is the same but types are different
auto at = arg.type.toChars();
bool qual = !arg.type.equals(par.type) && strcmp(at, par.type.toChars()) == 0;
if (qual)
at = arg.type.toPrettyChars(true);
OutBuffer as;
as.printf("`%s` of type `%s`", arg.toChars(), at);
OutBuffer ps;
ps.printf("`%s`", parameterToChars(par, this, qual));
OutBuffer buf;
buf.printf(format, as.peekString(), ps.peekString());
// only mention rvalue if it's relevant
const rv = !arg.isLvalue() && par.storageClass & (STC.ref_ | STC.out_);
const char* fmt = rv ?
"cannot pass rvalue argument `%s` of type `%s` to parameter `%s`" :
"cannot pass argument `%s` of type `%s` to parameter `%s`";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems a bit unnecessary to duplicate the whole format string when the only difference is rvalue. Perhaps rvalue can be passed as a parameter to printf as well?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, last time I tried something in this direction, it was complained that this increases the binary size.
It's just "cannot pass%s" and then rv ? " rvalue" : "", no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix is here: ntrel@6219e5e

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool. Would you mind submitting it as PR too? Thanks!

buf.printf(fmt, arg.toChars(), at, parameterToChars(par, this, qual));
return buf.extractString();
}

Expand Down Expand Up @@ -4935,7 +4936,7 @@ extern (C++) final class TypeFunction : TypeNext
{
if (p.storageClass & STC.out_)
{
if (pMessage) *pMessage = getParamError("cannot pass rvalue argument %s to parameter %s", arg, p);
if (pMessage) *pMessage = getParamError(arg, p);
goto Nomatch;
}

Expand All @@ -4960,7 +4961,7 @@ extern (C++) final class TypeFunction : TypeNext
}
else
{
if (pMessage) *pMessage = getParamError("cannot pass rvalue argument %s to parameter %s", arg, p);
if (pMessage) *pMessage = getParamError(arg, p);
goto Nomatch;
}
}
Expand All @@ -4987,9 +4988,7 @@ extern (C++) final class TypeFunction : TypeNext
*/
if (!ta.constConv(tp))
{
if (pMessage) *pMessage = getParamError(
arg.isLvalue() ? "cannot pass argument %s to parameter %s" :
"cannot pass rvalue argument %s to parameter %s", arg, p);
if (pMessage) *pMessage = getParamError(arg, p);
goto Nomatch;
}
}
Expand Down Expand Up @@ -5049,7 +5048,7 @@ extern (C++) final class TypeFunction : TypeNext

if (m == MATCH.nomatch)
{
if (pMessage) *pMessage = getParamError("cannot pass argument %s to parameter %s", arg, p);
if (pMessage) *pMessage = getParamError(arg, p);
goto Nomatch;
}
if (m < match)
Expand All @@ -5067,7 +5066,7 @@ extern (C++) final class TypeFunction : TypeNext
}
}
if (pMessage && u < nargs)
*pMessage = getParamError("cannot pass argument %s to parameter %s", (*args)[u], p);
*pMessage = getParamError((*args)[u], p);
goto Nomatch;
}
if (m < match)
Expand Down
15 changes: 15 additions & 0 deletions test/fail_compilation/bug15613.d
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,18 @@ void main()
f(null);
g(8);
}

/*
TEST_OUTPUT:
---
fail_compilation/bug15613.d(32): Error: function `bug15613.h(int[]...)` is not callable using argument types `(int, void function(int[]...))`
fail_compilation/bug15613.d(32): cannot pass argument `& h` of type `void function(int[]...)` to parameter `int[]...`
---
*/

void h(int[]...);

void test()
{
h(7, &h);
}