"I made a game using Rust"

Adrian Matoga via Digitalmars-d digitalmars-d at puremagic.com
Wed May 10 08:50:06 PDT 2017


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/eoxerbkaowxpgjubhdqq@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


More information about the Digitalmars-d mailing list