opDispatch, duck typing, and error messages

Adam D. Ruppe destructionator at gmail.com
Thu Apr 21 15:24:55 PDT 2011


I just made an innocent little change to one of my programs, hit
compile, and got this vomit:

/home/me/d/dmd2/linux/bin/../../src/phobos/std/conv.d(97): Error: template
std.conv.toImpl(T,S) if (!implicitlyConverts!(S,
T) && isSomeString!(T) && isInputRange!(Unqual!(S)) &&
isSomeChar!(ElementType!(S))) toImpl(T,S) if (!implicitlyConverts!(S
,T) && isSomeString!(T) && isInputRange!(Unqual!(S)) &&
isSomeChar!(ElementType!(S))) matches more than one template declar
ation, /home/me/d/dmd2/linux/bin/../../src/phobos/std/conv.d(185):toImpl(T,S)
if (isSomeString!(T) && !isSomeChar!(ElementT
ype!(S)) && (isInputRange!(S) || isInputRange!(Unqual!(S)))) and
/home/me/d/dmd2/linux/bin/../../src/phobos/std/conv.d(289)
:toImpl(T,S) if (is(S : Object) && isSomeString!(T))



Whooooo... took a bit to figure out what it was saying. The bottom
line: one of my classes matched both Object and isInputRange because
it offers an unrestricted opDispatch.

The fix:

// note the constraint
string opDispatch(string name)() if(name != "popFront") {}


(I'm sure empty or front would have worked just as well, but popFront
I'm sure I didn't actually use anywhere for this.)


This post is to serve as two things: an FYI in case you see something
like this yourself, and to have a discussion on what we can do to
improve the situation.

A constraint like this wouldn't work of the Object was actually
supposed to be a range.


So, what can we do to improve that message? As it is now, it's
close to useless. Yeah, I was able to track down what it meant, but
only after I hacked up my copy of Phobos to tell me what T and S
actually were in the instantiation of to... then, it was obvious what
the error meant, but before, well, I pity the poor newbie who
stumbles upon that!


Things I think would help:

a) If the compiler gave some kind of stack trace in this instance. An
error message pointing solely at std.conv doesn't help much. In a
lot of template error messages, the kind of trace I want
already exists, so I suspect 90% of the work to implement it is
already done.

b) Format those constraints a little. Just put a "\n\t" before the
if and a "\n" before the function name. I think some whitespace
would help a lot in readability. Sure, newbs might still not get it,
but at least it won't be a blob of wtf.

Alas, I've looked at the compiler, but aren't to the point where I
can contribute code to it myself. Well, maybe I could do the
formatting change, but I haven't tried yet.

Regardless, let's look at other options.


c) Maybe Phobos could help out somehow? Another thing to!()
annoys the living crap of me with is it's runtime errors. It, again,
doesn't tell me where in my code the problem occurred.

Perhaps have it take default __FILE__ and __LINE__ args to print out
too? I think this can help both compile and runtime errors.

d) Also in Phobos, I wonder if we can beautify the message somehow.
I don't have any idea how to do this in a scalable way.

It could static if (matches constraint 1 and constraint 2)
static assert("pretty message"), but there's no chance that would
scale well.

So I don't know here.


Or, there's a whole new approach:

e) Duck typing for ranges in to!() might be a bad idea. Again, remember,
a class might legitimately offer a range interface, so it would
trigger this message without opDispatch.

If ranges are meant to be structs, maybe isInputRange should check
is(T == struct)? This doesn't sit right with me though. The real
problem is to!() - other range functions probably don't overload
on classes separately than ranges, so it won't matter there.


I think the best thing to do is simply to prefer Object over range.

toImpl(T) if (isInputRange!(T) && (!is(T : Object)))

Or something along those lines. Why? If the object has it's own
toString/writeTo methods, it seems fairly obvious to me anyway that
to!string ought to simply call them, regardless or what else there is.



I kinda blabbered here, but in the end, I think my previous paragraph
is the big thing. It's a fairly minor Phobos change. Any objections
to it?

Note btw that I'd still like the error messages to be prettier, but
I'm ok doing it one step at a time.


More information about the Digitalmars-d mailing list