Help from the compiler when debugging failing template constraints - a pull request

Atila Neves via Digitalmars-d digitalmars-d at puremagic.com
Mon Sep 28 13:25:20 PDT 2015


I've mentioned this many times before: template constraints are 
like unittest blocks with asserts in D: great that they're 
built-in easy to use. But when they fail, there's no help in 
figuring out why.

I've had many a debugging session (with pragma(msg) of course, 
since my bugs were of the compile-time variety and there's no 
debugger for that) due to failing to satisfy a template 
constraint that I thought I'd implemented the correct functions 
for. It'd be nice if the compiler told me why. I did a PR a while 
back with an idea from Adam's book but it didn't work in the 
context of Phobos and interfaces. I've come up with a PR 
(https://github.com/D-Programming-Language/phobos/pull/3677) that 
will let users type this:

     @models!(MyStruct, isInputRange)
     struct MyStruct { ... }

Or this:

     struct MyStruct {
         ...
         static assert(models!(MyStruct, isInputRange));
     }

When the template constraint isn't satisfied, the compiler will 
dutifully tell you why. The only requirement is that there be a 
checkXXX function for an isXXX template constraint. I've updated 
the original PR for `isInputRange` to make the above code 
possible. I chose the name `models` because I just got back from 
CppCon and concepts might have tainted my brain. It's unfortunate 
to have to specify the type in the UDA version, but it's what the 
language as it is now will allow me to do.

I created an input range, verified it compiled, then added a 't' 
to the end of `front`. With `models` I got this for both UDA and 
static assert versions:

/home/atila/coding/d/dlang/phobos/std/range/primitives.d(182): 
Error: template std.range.primitives.front cannot deduce function 
from argument types !()(Foo), candidates are:
/home/atila/coding/d/dlang/phobos/std/range/primitives.d(2219):   
      std.range.primitives.front(T)(T[] a) if 
(!isNarrowString!(T[]) && !is(T[] == void[]))
/home/atila/coding/d/dlang/phobos/std/range/primitives.d(2247):   
      std.range.primitives.front(T)(T[] a) if 
(isNarrowString!(T[]))
/home/atila/coding/d/dlang/phobos/std/traits.d-mixin-6771(6771): 
Error: template instance 
std.range.primitives.checkInputRange!(Foo) error instantiating
concepts.d(81):        instantiated from here: models!(Foo, 
isInputRange)
Failed: ["dmd", "-unittest", "-main", "-v", "-o-", "concepts.d", 
"-I."]


With `static assert(isInputRange!Foo)`, I get this:

concepts.d(87): Error: static assert  (isInputRange!(Foo)) is 
false
Failed: ["dmd", "-unittest", "-main", "-v", "-o-", "concepts.d", 
"-I."]

I prefer the first one. How about you?

Atila




More information about the Digitalmars-d mailing list