Help improve error message

Steven Schveighoffer schveiguy at gmail.com
Sun May 7 14:19:49 UTC 2023


On 5/6/23 4:02 PM, ryuukk_ wrote:
> First of all, a little quiz
> 
> 
> What should the error message be for the following code?
> 
> ```D
> struct Something{}
> 
> void main()
> {
>      Something test;
>      test.get();
> }
> ```
> 
> 
> Well.. it's not what you expect..

Depends ;) I've been using D long enough that it's exactly what I expected.

> 
> There is the actual error message, surprising right?
> 
> ``Something`` is not an associative array, so why AA's functions are in 
> the candidate list?
> 
> What ``Something`` has to do with ``object.get``??
> 
> 
> The correct and desirable error message should be:
> 
> ```
> Error: no property `get` for `test` of type `Something`
> ```
> 
> Not something confusing and misleading.. that's hard to debug
> 
> Do you agree with that?
> 
> If you do and want to improve D, then join me and try to fix that behavior!
> 
> 
> 2 possible solutions that i can think of:
> 
> - functions in ``object.d`` should be cleaned, everything that has to do 
> with ``AA`` should only work with ``AA``, and everything that is 
> generic, should be renamed so it doesn't produce conflicts
> 
> - DMD should be smarter and the logic for resolving the function should 
> reject these functions, so it can produce the proper error message

So the thing about this -- you know what you meant. The compiler 
doesn't. In cases where you thought you were using an AA, but weren't, 
this message is very helpful.

When faced with an ambiguity, the compiler has to say something. It says 
what it thinks you wanted it to do, and why that doesn't work. It can't 
read your mind and understand what you thought was going to happen. It 
can't think about what a reasonable person might have done, because it 
doesn't have that power.

If we make it say something different, it's going to confuse another 
developer with another situation. This is why we have so much structure 
around code -- to give the compiler anchor points and delineations to 
try and make it easier to understand what is being asked of it. We do 
the best we can think of to make error messages reflect the predicted 
behavior of people. But it can't be perfect.

UFCS greatly expands the universe of "what you might have meant", and so 
we have the sometimes-bizarre error cases that show up. My 
recommendation is just to get used to what that means. I don't see a 
good way to fix this.

I'll give you another example, one which I just recently fixed (will be 
soon deprecated, and then eventually removed): core.time has a `to` 
function. If you want to use the regular `to` and forgot to import 
`std.conv`, but had imported `core.time`, or imported `core.time` in a 
way that overrides `std.conv` (i.e. locally in a function), you would 
see a bizarre message:

```d
import core.time;

void main()
{
   auto x = "12345".to!int;
}
```

```
onlineapp.d(5): Error: none of the overloads of template `core.time.to` 
are callable using argument types `!(int)(string)`
/dlang/dmd/linux/bin64/../../src/druntime/import/core/time.d(1776): 
   Candidate is: `to(string units, T, D)(D td)`
```

However, if you don't import `core.time`, you get the better error message:

```
onlineapp.d(5): Error: no property `to` for type `string`, perhaps 
`import std.conv;` is needed?
```

Turns out core.time.to is only used for a completely deprecated type 
`TickDuration`, and so we can remove it completely. There's the fix for 
that. We can't do the same for `object.get`.

-Steve


More information about the Digitalmars-d mailing list