mirror of
https://github.com/dlang/dmd.git
synced 2025-04-27 21:51:03 +03:00
Improve opIndex/opSlice error messages (#20791)
This commit is contained in:
parent
cfd2dde588
commit
a55dff5f28
6 changed files with 95 additions and 29 deletions
|
@ -30,12 +30,26 @@ Error: `app.bar` called with argument types `(string)` matches multiple overload
|
||||||
*/
|
*/
|
||||||
---
|
---
|
||||||
|
|
||||||
When there's no operator overload found for a type, a new supplemental message points to the declaration.
|
When there's no index / slice operator overload found for a type, a new supplemental message suggests where to implement it.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
struct S {}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
S s;
|
||||||
|
const x = s[3 .. "4"];
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
app.d(8): Error: no `[]` operator overload for type `U`
|
Before:
|
||||||
app.d(6): `app.U` declared here
|
|
||||||
|
app.d(6): Error: no `[]` operator overload for type `S`
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
app.d(6): Error: no `[3.."4"]` operator overload for type `S`
|
||||||
|
app.d(1): perhaps define `auto opSlice(int lower, string upper) {}` for `app.S`
|
||||||
*/
|
*/
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -9705,9 +9705,40 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto ad = isAggregate(exp.e1.type))
|
if (auto ad = isAggregate(exp.e1.type))
|
||||||
|
{
|
||||||
|
if (exp.arguments.length == 0)
|
||||||
{
|
{
|
||||||
error(exp.loc, "no `[]` operator overload for type `%s`", exp.e1.type.toChars());
|
error(exp.loc, "no `[]` operator overload for type `%s`", exp.e1.type.toChars());
|
||||||
errorSupplemental(ad.loc, "`%s` declared here", ad.toPrettyChars());
|
errorSupplemental(ad.loc, "perhaps define `auto opIndex() {}` for `%s`", ad.toPrettyChars());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const(char)* typeString(Expression exp)
|
||||||
|
{
|
||||||
|
if (auto e = exp.trySemantic(sc))
|
||||||
|
return e.type.toChars();
|
||||||
|
else
|
||||||
|
return "__error__";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto ie = (*exp.arguments)[0].isIntervalExp())
|
||||||
|
{
|
||||||
|
error(exp.loc, "no `[%s]` operator overload for type `%s`", ie.toChars(), exp.e1.type.toChars());
|
||||||
|
errorSupplemental(ad.loc, "perhaps define `auto opSlice(%s lower, %s upper) {}` for `%s`",
|
||||||
|
typeString(ie.lwr), typeString(ie.upr), ad.toPrettyChars());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OutBuffer buf;
|
||||||
|
buf.printf("%s", typeString((*exp.arguments)[0]));
|
||||||
|
foreach (e; (*exp.arguments)[1 .. $])
|
||||||
|
buf.printf(", %s", typeString(e));
|
||||||
|
|
||||||
|
error(exp.loc, "no `[]` operator overload for type `%s`", exp.e1.type.toChars());
|
||||||
|
errorSupplemental(ad.loc, "perhaps define `auto opIndex(%s) {}` for `%s`",
|
||||||
|
buf.extractChars, ad.toPrettyChars());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
|
else if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
|
||||||
error(exp.loc, "static array of `%s` with multiple lengths not allowed", exp.e1.type.toChars());
|
error(exp.loc, "static array of `%s` with multiple lengths not allowed", exp.e1.type.toChars());
|
||||||
|
|
|
@ -403,9 +403,9 @@ Expression opOverloadArray(ArrayExp ae, Scope* sc)
|
||||||
|
|
||||||
if (result.op == EXP.error)
|
if (result.op == EXP.error)
|
||||||
{
|
{
|
||||||
if (!e0 && !search_function(ad, Id.dollar)) {
|
if (!e0 && !search_function(ad, Id.dollar))
|
||||||
ae.loc.errorSupplemental("Aggregate declaration '%s' does not define 'opDollar'", ae.e1.toChars());
|
ad.loc.errorSupplemental("perhaps define `opDollar` for `%s`", ad.toChars());
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
/* Rewrite a[i..j] as:
|
/* Rewrite a[i..j] as:
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
TEST_OUTPUT:
|
TEST_OUTPUT:
|
||||||
---
|
---
|
||||||
fail_compilation/fail20616.d(16): Error: undefined identifier `$`
|
fail_compilation/fail20616.d(16): Error: undefined identifier `$`
|
||||||
fail_compilation/fail20616.d(16): Aggregate declaration 'X()' does not define 'opDollar'
|
fail_compilation/fail20616.d(13): perhaps define `opDollar` for `X`
|
||||||
fail_compilation/fail20616.d(18): Error: undefined identifier `$`
|
fail_compilation/fail20616.d(18): Error: undefined identifier `$`
|
||||||
fail_compilation/fail20616.d(18): Aggregate declaration 'b' does not define 'opDollar'
|
fail_compilation/fail20616.d(13): perhaps define `opDollar` for `X`
|
||||||
---
|
---
|
||||||
*/
|
*/
|
||||||
module fail20616;
|
module fail20616;
|
||||||
|
|
|
@ -6,7 +6,7 @@ fail_compilation/fail_arrayexp.d(25): Error: cannot use `[]` operator on express
|
||||||
fail_compilation/fail_arrayexp.d(26): Error: static array of `const(int)[]` with multiple lengths not allowed
|
fail_compilation/fail_arrayexp.d(26): Error: static array of `const(int)[]` with multiple lengths not allowed
|
||||||
fail_compilation/fail_arrayexp.d(27): Error: only one index allowed to index `string`
|
fail_compilation/fail_arrayexp.d(27): Error: only one index allowed to index `string`
|
||||||
fail_compilation/fail_arrayexp.d(28): Error: no `[]` operator overload for type `U`
|
fail_compilation/fail_arrayexp.d(28): Error: no `[]` operator overload for type `U`
|
||||||
fail_compilation/fail_arrayexp.d(16): `fail_arrayexp.U` declared here
|
fail_compilation/fail_arrayexp.d(16): perhaps define `auto opIndex() {}` for `fail_arrayexp.U`
|
||||||
fail_compilation/fail_arrayexp.d(29): Error: only one index allowed to index `(int, string)`
|
fail_compilation/fail_arrayexp.d(29): Error: only one index allowed to index `(int, string)`
|
||||||
---
|
---
|
||||||
*/
|
*/
|
||||||
|
@ -29,3 +29,24 @@ void test19534() // https://issues.dlang.org/show_bug.cgi?id=19534
|
||||||
auto t = agg[];
|
auto t = agg[];
|
||||||
auto u = getTuple!(int, string)[1, 2];
|
auto u = getTuple!(int, string)[1, 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TEST_OUTPUT:
|
||||||
|
---
|
||||||
|
fail_compilation/fail_arrayexp.d(49): Error: no `[3.."4"]` operator overload for type `S`
|
||||||
|
fail_compilation/fail_arrayexp.d(42): perhaps define `auto opSlice(int lower, string upper) {}` for `fail_arrayexp.S`
|
||||||
|
fail_compilation/fail_arrayexp.d(50): Error: no `[]` operator overload for type `S`
|
||||||
|
fail_compilation/fail_arrayexp.d(42): perhaps define `auto opIndex(int, string, char) {}` for `fail_arrayexp.S`
|
||||||
|
---
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct S
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void testSlice()
|
||||||
|
{
|
||||||
|
S s;
|
||||||
|
const b = s[3 .. "4"];
|
||||||
|
const c = s[3, "4", 'c'];
|
||||||
|
}
|
||||||
|
|
|
@ -4,33 +4,33 @@
|
||||||
TEST_OUTPUT:
|
TEST_OUTPUT:
|
||||||
---
|
---
|
||||||
fail_compilation/fail_opover.d(39): Error: no `[]` operator overload for type `object.Object`
|
fail_compilation/fail_opover.d(39): Error: no `[]` operator overload for type `object.Object`
|
||||||
$p:object.d$(110): `object.Object` declared here
|
$p:object.d$(110): perhaps define `auto opIndex() {}` for `object.Object`
|
||||||
fail_compilation/fail_opover.d(43): Error: no `[]` operator overload for type `TestS`
|
fail_compilation/fail_opover.d(43): Error: no `[]` operator overload for type `TestS`
|
||||||
fail_compilation/fail_opover.d(41): `fail_opover.test1.TestS` declared here
|
fail_compilation/fail_opover.d(41): perhaps define `auto opIndex() {}` for `fail_opover.test1.TestS`
|
||||||
fail_compilation/fail_opover.d(55): Error: no `[]` operator overload for type `S`
|
fail_compilation/fail_opover.d(55): Error: no `[]` operator overload for type `S`
|
||||||
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
|
fail_compilation/fail_opover.d(48): perhaps define `auto opIndex() {}` for `fail_opover.test2.S`
|
||||||
fail_compilation/fail_opover.d(56): Error: no `[]` operator overload for type `S`
|
fail_compilation/fail_opover.d(56): Error: no `[]` operator overload for type `S`
|
||||||
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
|
fail_compilation/fail_opover.d(48): perhaps define `auto opIndex(int) {}` for `fail_opover.test2.S`
|
||||||
fail_compilation/fail_opover.d(57): Error: no `[]` operator overload for type `S`
|
fail_compilation/fail_opover.d(57): Error: no `[1..2]` operator overload for type `S`
|
||||||
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
|
fail_compilation/fail_opover.d(48): perhaps define `auto opSlice(int lower, int upper) {}` for `fail_opover.test2.S`
|
||||||
fail_compilation/fail_opover.d(58): Error: no `[]` operator overload for type `S`
|
fail_compilation/fail_opover.d(58): Error: no `[]` operator overload for type `S`
|
||||||
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
|
fail_compilation/fail_opover.d(48): perhaps define `auto opIndex() {}` for `fail_opover.test2.S`
|
||||||
fail_compilation/fail_opover.d(59): Error: no `[]` operator overload for type `S`
|
fail_compilation/fail_opover.d(59): Error: no `[]` operator overload for type `S`
|
||||||
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
|
fail_compilation/fail_opover.d(48): perhaps define `auto opIndex(int) {}` for `fail_opover.test2.S`
|
||||||
fail_compilation/fail_opover.d(60): Error: no `[]` operator overload for type `S`
|
fail_compilation/fail_opover.d(60): Error: no `[1..2]` operator overload for type `S`
|
||||||
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
|
fail_compilation/fail_opover.d(48): perhaps define `auto opSlice(int lower, int upper) {}` for `fail_opover.test2.S`
|
||||||
fail_compilation/fail_opover.d(61): Error: no `[]` operator overload for type `S`
|
fail_compilation/fail_opover.d(61): Error: no `[]` operator overload for type `S`
|
||||||
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
|
fail_compilation/fail_opover.d(48): perhaps define `auto opIndex() {}` for `fail_opover.test2.S`
|
||||||
fail_compilation/fail_opover.d(62): Error: no `[]` operator overload for type `S`
|
fail_compilation/fail_opover.d(62): Error: no `[]` operator overload for type `S`
|
||||||
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
|
fail_compilation/fail_opover.d(48): perhaps define `auto opIndex(int) {}` for `fail_opover.test2.S`
|
||||||
fail_compilation/fail_opover.d(63): Error: no `[]` operator overload for type `S`
|
fail_compilation/fail_opover.d(63): Error: no `[1..2]` operator overload for type `S`
|
||||||
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
|
fail_compilation/fail_opover.d(48): perhaps define `auto opSlice(int lower, int upper) {}` for `fail_opover.test2.S`
|
||||||
fail_compilation/fail_opover.d(64): Error: no `[]` operator overload for type `S`
|
fail_compilation/fail_opover.d(64): Error: no `[]` operator overload for type `S`
|
||||||
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
|
fail_compilation/fail_opover.d(48): perhaps define `auto opIndex() {}` for `fail_opover.test2.S`
|
||||||
fail_compilation/fail_opover.d(65): Error: no `[]` operator overload for type `S`
|
fail_compilation/fail_opover.d(65): Error: no `[]` operator overload for type `S`
|
||||||
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
|
fail_compilation/fail_opover.d(48): perhaps define `auto opIndex(int) {}` for `fail_opover.test2.S`
|
||||||
fail_compilation/fail_opover.d(66): Error: no `[]` operator overload for type `S`
|
fail_compilation/fail_opover.d(66): Error: no `[1..2]` operator overload for type `S`
|
||||||
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
|
fail_compilation/fail_opover.d(48): perhaps define `auto opSlice(int lower, int upper) {}` for `fail_opover.test2.S`
|
||||||
---
|
---
|
||||||
*/
|
*/
|
||||||
void test1()
|
void test1()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue