Jump to page: 1 2
Thread overview
Help improve error message
May 06, 2023
ryuukk_
May 06, 2023
max haughton
May 08, 2023
RazvanN
May 07, 2023
Salih Dincer
May 07, 2023
Salih Dincer
May 08, 2023
ryuukk_
May 08, 2023
ryuukk_
May 08, 2023
Salih Dincer
May 09, 2023
Dennis
May 09, 2023
ryuukk_
May 08, 2023
Max Samukha
May 09, 2023
H. S. Teoh
May 06, 2023

First of all, a little quiz

What should the error message be for the following code?

struct Something{}

void main()
{
    Something test;
    test.get();
}

Well.. it's not what you expect..

onlineapp.d(6): Error: none of the overloads of template `object.get` are callable using argument types `!()(Something)`
/dlang/dmd/linux/bin64/../../src/druntime/import/object.d(3442):        Candidates are: `get(K, V)(inout(V[K]) aa, K key, lazy inout(V) defaultValue)`
/dlang/dmd/linux/bin64/../../src/druntime/import/object.d(3449):                        `get(K, V)(inout(V[K])* aa, K key, lazy inout(V) defaultValue)`

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

I am obviously clueless, so my 1st attempt was to remove the functions plain and simple, it works for me, but that's not the proper solution right..

I suspect that the problem lies here: https://github.com/dlang/dmd/blob/54b6a2f2b0a129fa3c4a994658d9f99e3a6d4ee3/compiler/src/dmd/func.d#L3265-L3485

Join me and let's make D better (join the IRC channel so we can chat about it)

May 06, 2023

On Saturday, 6 May 2023 at 20:02:30 UTC, ryuukk_ wrote:

>

First of all, a little quiz

What should the error message be for the following code?

struct Something{}

void main()
{
    Something test;
    test.get();
}

Well.. it's not what you expect..

onlineapp.d(6): Error: none of the overloads of template `object.get` are callable using argument types `!()(Something)`
/dlang/dmd/linux/bin64/../../src/druntime/import/object.d(3442):        Candidates are: `get(K, V)(inout(V[K]) aa, K key, lazy inout(V) defaultValue)`
/dlang/dmd/linux/bin64/../../src/druntime/import/object.d(3449):                        `get(K, V)(inout(V[K])* aa, K key, lazy inout(V) defaultValue)`

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

This wouldn't be that hard to do but then you have a tradeoff between making this cleaner and making other contexts more confusing.

On the compiler side it would be interesting to make it output some kind of prose based on some kind of type pattern matching / unification e.g. rather than saying "Cannot call X with Y", we'd have a much more contextual error message that uses the information in the template signature (e.g. for (K, V)(inout(V[K]) to be matched, it must satisfy the pattern, so must be an AA of type V[K]).

There's a dlang/projects entry for error messages, this would make a good thing to be done in that project.

As for the runtime, I'm not a big fan of these free functions either.

May 07, 2023

On Saturday, 6 May 2023 at 20:02:30 UTC, ryuukk_ wrote:

>

...
it's not what you expect..

onlineapp.d(6): Error: none of the overloads of template `object.get` are callable using argument types `!()(Something)`
/dlang/dmd/linux/bin64/../../src/druntime/import/object.d(3442):        Candidates are: `get(K, V)(inout(V[K]) aa, K key, lazy inout(V) defaultValue)`
/dlang/dmd/linux/bin64/../../src/druntime/import/object.d(3449):                        `get(K, V)(inout(V[K])* aa, K key, lazy inout(V) defaultValue)`

There is the actual error message, surprising right?

The interesting thing is that we encountered this error in previous versions (eg. v2.087). It hasn't been tried in all versions, but I'm sure this error will appear at some version. I encountered this once as well.

Now I tried with the following code. Yes, even with the latest version I got the same error. However, DMD has such an advanced error and suggestion mechanism that it guides you how to use opAssign correctly.

struct Something {
  void opAssign(int) {

  }
}

void main() {
     Something test;/* = 1; /*
     `test = 1` is the first assignment of `test` therefore it represents its initialization
     `opAssign` methods are not used for initialization, but for subsequent assignments//*/

      test = 1;/*
      // Error: no overload matches for `get`
      test.get();//*/
      writeln(__VERSION__*.001); // 2.087
}

SDB@79

May 07, 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?

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:

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

May 07, 2023
On Sunday, 7 May 2023 at 14:19:49 UTC, Steven Schveighoffer wrote:
> 
> There's the fix for that. We can't do the same for `object.get`.

Why?

I do not accept this. Because this problem has a reason! Something happened after D Compiler v2.096! If you import the std.net.curl module, you get the error code we want.

For example you can try here:
https://wandbox.org/permlink/0I2x7W9kM6e94vl2

SDB@79


May 08, 2023

On Sunday, 7 May 2023 at 14:19:49 UTC, Steven Schveighoffer wrote:

> >

Well.. it's not what you expect..

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

See.. that's were my expectation of this language seems to be non-compatible with the majority of you, and that's super unfortunate because there is nothing i can do to change things

Something is a struct, and you are telling me that it is normal for D to treat it as a associative array

With that kind of expectation, i now understand better why the .enum DIP got shut down, language is stuck in the past with no way to improve anything, including this type identity crisis

May 07, 2023

On 5/7/23 8:50 PM, ryuukk_ wrote:

>

On Sunday, 7 May 2023 at 14:19:49 UTC, Steven Schveighoffer wrote:

> >

Well.. it's not what you expect..

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

See.. that's were my expectation of this language seems to be non-compatible with the majority of you, and that's super unfortunate because there is nothing i can do to change things

Something is a struct, and you are telling me that it is normal for D to treat it as a associative array

No, it's normal that the name get when not defined on a type then tries UFCS. And because I know get is a UFCS function in object.d, it will pick that up instead of saying "no such function".

What if Something had a function called get, but it didn't take the parameters you sent it? Would it be acceptable to you if it said "no function named get" instead of detailing why the parameters don't match? That's basically what you are asking.

>

With that kind of expectation, i now understand better why the .enum DIP got shut down, language is stuck in the past with no way to improve anything, including this type identity crisis

This is unrelated. UFCS is a fabulous feature of the language, and understanding the way it works is crucial in order to understand the confusing error messages you might see. Not that it's always ideal, but I'll take confusing messages and UFCS over the alternative without UFCS any day.

FWIW, I was in favor of the enum DIP and think the reasons for rejection were invalid. But I've also been here long enough to know when arguing over the dead horse isn't worth my time.

-Steve

May 08, 2023

On Monday, 8 May 2023 at 02:55:57 UTC, Steven Schveighoffer wrote:

>

On 5/7/23 8:50 PM, ryuukk_ wrote:

>

On Sunday, 7 May 2023 at 14:19:49 UTC, Steven Schveighoffer wrote:

> >

Well.. it's not what you expect..

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

See.. that's were my expectation of this language seems to be non-compatible with the majority of you, and that's super unfortunate because there is nothing i can do to change things

Something is a struct, and you are telling me that it is normal for D to treat it as a associative array

No, it's normal that the name get when not defined on a type then tries UFCS. And because I know get is a UFCS function in object.d, it will pick that up instead of saying "no such function".

What if Something had a function called get, but it didn't take the parameters you sent it? Would it be acceptable to you if it said "no function named get" instead of detailing why the parameters don't match? That's basically what you are asking.

>

With that kind of expectation, i now understand better why the .enum DIP got shut down, language is stuck in the past with no way to improve anything, including this type identity crisis

This is unrelated. UFCS is a fabulous feature of the language, and understanding the way it works is crucial in order to understand the confusing error messages you might see. Not that it's always ideal, but I'll take confusing messages and UFCS over the alternative without UFCS any day.

FWIW, I was in favor of the enum DIP and think the reasons for rejection were invalid. But I've also been here long enough to know when arguing over the dead horse isn't worth my time.

-Steve

You don't understand, my complain isn't about UFCS, it's about the error message that is misleading when trying to debug a problem in your project, the compiler never gives you the hint that Something doesn't have a get function, it tells you that in some other places it doesn't match any overload, it's perhaps time saved when you were looking to use an UFCS function, but it is time wasted when you were looking to call a function from Something

I perhaps expect the following error message:

onlineapp.d(6): Error: no property `get` for `test` of type `Something`
onlineapp.d(6): Note: The following UFCS functions where found:

    /dlang/dmd/linux/bin64/../../src/druntime/import/object.d(3442):
        `get(K, V)(inout(V[K]) aa, K key, lazy inout(V) defaultValue)`
    /dlang/dmd/linux/bin64/../../src/druntime/import/object.d(3449):
        `get(K, V)(inout(V[K])* aa, K key, lazy inout(V) defaultValue)`

onlineapp.d(6): Error: none of the overloads of template `object.get` are callable using argument types `!()(Something)`

If your language has good feature, diagnostics should match, otherwise it's like with this global that can't be debugged, you perhaps learned to live with it, i haven't and refuse to do so

May 08, 2023

On Monday, 8 May 2023 at 03:31:10 UTC, ryuukk_ wrote:

>

... my complain isn't about UFCS, it's about the error message that is misleading when trying to debug a problem in your project, the compiler never gives you the hint...

I put signature under what you say! Obviously, UFCS doesn't get along well with DMD. There is an extra get() function as you will see below. This causes the error message [¹] to change completely.

struct S {}

void main() {
  S s;
  s.get();
}

void get() {}

I don't think there can be a sluggish compiler like DMD! It's bullshit. Definitely it needs to be recoded. It's like a rag bag all over.

[¹] onlineapp.d(5): Error: function onlineapp.get() is not callable using
argument types (S)
onlineapp.d(5): expected 0 argument(s), not 1

SDB@79

May 08, 2023

On Monday, 8 May 2023 at 02:55:57 UTC, Steven Schveighoffer wrote:

>

UFCS is a fabulous feature of the language,

It would be fabulous if:

  1. it worked with operators
  2. overload sets of member and global functions were supported
  3. there are other issues with it, but I can't remember what
« First   ‹ Prev
1 2