Bug 16059 – needed better error messages for failed overloads

Status
RESOLVED
Resolution
WORKSFORME
Severity
enhancement
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2016-05-23T00:07:19Z
Last change time
2022-11-09T14:33:15Z
Assigned to
No Owner
Creator
Piotr

Comments

Comment #0 by poliklosio.dlang — 2016-05-23T00:07:19Z
I think I may have an idea for a usable solution to improve error messages. Example of an error I got from dmd: C:\D\dmd2\windows\bin\..\..\src\phobos\std\conv.d(298,24): Error: template std.conv.toImpl cannot deduce function from argument types !(ubyte[])(RangeT!(Array!ubyte)), candidates are: C:\D\dmd2\windows\bin\..\..\src\phobos\std\conv.d(364,3): std.conv.toImpl(T, S)(S value) if (isImplicitlyConvertible!(S, T) && !isEnumStrToStr!(S, T) && !isNullToStr!(S, T)) C:\D\dmd2\windows\bin\..\..\src\phobos\std\conv.d(478,3): std.conv.toImpl(T, S)(ref S s) if (isRawStaticArray!S) C:\D\dmd2\windows\bin\..\..\src\phobos\std\conv.d(494,3): std.conv.toImpl(T, S)(S value) if (!isImplicitlyConvertible!(S, T) && is(typeof(S.init.opCast!T()) : T) && !isExactSomeString!T && !is(typeof(T(value)))) C:\D\dmd2\windows\bin\..\..\src\phobos\std\conv.d(545,3): std.conv.toImpl(T, S)(S value) if (!isImplicitlyConvertible!(S, T) && is(T == struct) && is(typeof(T(value)))) C:\D\dmd2\windows\bin\..\..\src\phobos\std\conv.d(594,3): std.conv.toImpl(T, S)(S value) if (!isImplicitlyConvertible!(S, T) && is(T == class) && is(typeof(new T(value)))) C:\D\dmd2\windows\bin\..\..\src\phobos\std\conv.d(298,24): ... (9 more, -v to show) ... src\app.d(36,36): Error: template instance std.conv.to!(ubyte[]).to!(RangeT!(Array!ubyte)) error instantiating dmd failed with exit code 1. There are multiple problems with this error message: - The information that the source of the problem was the call to a "to" function is not at the top. - It is missing some very important information, in particular the general idea of what types are accepted by the "to" function. It only shows the way the constrains are *implemented*, it doesn't tell directly what the author wanted to achieve. When one writes 20 overloads, its usually because there is some commmon property among the accepted types which cannot be easily expressed with the type system. - It doesn't show any useful speculation as to what mith be the cause of the error in this particular use case. There was a forum thread started by Andrei about other improvements to messages already: http://forum.dlang.org/post/[email protected] but it was focused on generating better messages from the constraints themselves, which is, IMHO, an inferior solution if not a lost cause. I would like to propose another solution which may improve experience regardless of the number of overloads, architecture of constrains and all the other technical issues, by laveraging the expressive power of English language. If the library writer could write something like this (example for the std.conv.to case): pragma(on_overload_resolution_error, "toImpl", " You used the \"to\" function incorrectly which failed at the point of toImpl template instantiation. The \"to\" function is meant for simple convertions which typically preserve the converted value, for example from double -> int, or double[] -> int[]. Typical mistakes when calling the \"to\" function involve: Calling on range types rather than arrays... ") This tells the compiler to display the "You used the ..." message at the top of the appropriate error message, in case there is an overload resolution error when using the toImpl function.
Comment #1 by razvan.nitu1305 — 2022-11-09T14:33:15Z
Errors have been improved since then and you also get to see which part of the constraint failed. I would consider that this is a satisfactory development since this bug report was filed. Sample: void fun(T)(T) if (is(T == int) || is(T == string)) {} void fun(T)(T) if (is(T == float)) {} struct A {} void main() { fun!A(A()); } yields: onlineapp.d(13): Error: none of the overloads of template `onlineapp.fun` are callable using argument types `!(A)(A)` onlineapp.d(1): Candidates are: `fun(T)(T)` with `T = A` must satisfy one of the following constraints: ` is(T == int) is(T == string)` onlineapp.d(5): `fun(T)(T)` with `T = A` must satisfy the following constraint: ` is(T == float)` This tells you exactly what failed.