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

Steven Schveighoffer via Digitalmars-d digitalmars-d at puremagic.com
Tue Sep 29 08:44:22 PDT 2015


On 9/28/15 4:25 PM, Atila Neves wrote:
> 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?

Yes. I also prefer that the compiler do this. I've definitely run into 
this before: http://forum.dlang.org/post/m4mdsk$bgs$1@digitalmars.com

-Steve


More information about the Digitalmars-d mailing list