On Wednesday, 10 May 2017 at 15:03:19 UTC, Adam D. Ruppe wrote:
On Wednesday, 10 May 2017 at 14:02:38 UTC, Adrian Matoga wrote:
Would you mind giving some examples?

What bothers me on a regular basis is overloading. Basic case:

$ dmd lll
lll.d(6): Error: none of the overloads of 'foo' are callable using argument types (int, double), candidates are:
lll.d(1):        lll.foo(int a, int a)
lll.d(2):        lll.foo(int a, string s)

Contrast that to g++:

$ g++ lll.cpp
lll.cpp: In function ‘int main()’:
lll.cpp:7:14: error: no matching function for call to ‘foo(int, Foo)’
  foo(0, Foo());
              ^
lll.cpp:7:14: note: candidates are:
lll.cpp:1:6: note: void foo(int, char*)
 void foo(int a, char* b);
      ^
lll.cpp:1:6: note: no known conversion for argument 2 from ‘Foo’ to ‘char*’
lll.cpp:2:6: note: void foo(int, float)
 void foo(int a, float b);
      ^
lll.cpp:2:6: note: no known conversion for argument 2 from ‘Foo’ to ‘float’



The g++ example isn't great either... but is better because of this: "no known conversion for argument 2 from ‘Foo’ to ‘float’"


It actually told me which argument didn't match! clang is similar:

$ clang lll.cpp
lll.cpp:7:2: error: no matching function for call to 'foo'
        foo(0, Foo());
        ^~~
lll.cpp:1:6: note: candidate function not viable: no known conversion from 'Foo' to 'char *' for 2nd argument
void foo(int a, char* b);
     ^
lll.cpp:2:6: note: candidate function not viable: no known conversion from 'Foo' to 'float' for 2nd argument
void foo(int a, float b);



With the dmd one, especially on a long function, it is hard to tell just which argument is giving trouble. The C++ errors just flat out tell me which argument didn't match for each candidate.

In this simple case above, I actually prefer DMD's messages, as there's simply less text for my eyes to read and brain to parse, so I can quickly spot where the problem is. I agree, though, that with longer argument lists, especially with const vs. non-const or template constraints, trying to figure out what's wrong could be at least frustrating.

Templates with constraints are even worse.

lll.d(3): Error: template std.algorithm.sorting.sort cannot deduce function from argument types !()(int), candidates are:
/home/me/d/dmd2/linux/bin32/../../src/phobos/std/algorithm/sorting.d(1830):        std.algorithm.sorting.sort(alias less = "a 
< b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r) if ((ss == SwapStrategy.unstable && 
(hasSwappableElements!Range || hasAssignableElements!Range) || ss != SwapStrategy.unstable && hasAssignableElements!Range) 
&& isRandomAccessRange!Range && hasSlicing!Range && hasLength!Range)


What a mess! Just formatting that output might help, but I'd especially love it if it told me which individual boolean elements failed, passed, and were short-circuited. The compiler knows this, it had to evaluate that to figure out it didn't match, but it doesn't tell me.

At a glance, can you even tell what I passed to the function?

Bonus points would be it telling me why, for example, `isInputRange` failed, but I understand that is an even bigger problem to solve.

It's indeed painful, but I found UDAs to be useful in dealing with it.
First, I'm sure you know Atila's concepts [1].

I also use UDAs in flod [2], so instead of checking whether the implementation satisfies a constraint, I only check if it's explicitly tagged with a specific UDA. Now, I immediately see whether it's a method that I forgot to implement or just a typo, instead of being forced to guess by a "missing overload" message.


Of course, C++ doesn't have constraints so there's no comparison there.


Lastly, check this out:

lll.d(5): Error: function lll.foo (Color c) is not callable using argument types (Color)

WTF, right? Well, I have a locally defined `struct Color` and an imported one. Same name, but different type. The error message doesn't tell me which one is which.

Yeah, that one was funny. :)

These are the top 3 dmd error messages that bother me regularly. At runtime, little drives me more nuts than RangeError not telling me the index and the length. Again, it knows, the code checked it, but it didn't report it.

Same with assertions. I usually end up adding wrappers like assertEqual, and the more I use them, the more I feel like switching to something like [3] or [4], as much as I normally prefer to keep the number of dependencies low.

I think RangeError could be solved without much effort by changing the compiler/runtime interface at _d_arraybounds*. Assertions are probably harder.


[1] http://forum.dlang.org/post/eoxerbkaowxpgjubh...@forum.dlang.org
[2] https://github.com/epi/flod/blob/develop/source/flod/package.d
[3] https://code.dlang.org/packages/fluent-asserts
[4] http://code.dlang.org/packages/unit-threaded

Reply via email to