Simple and effective approaches to constraint error messages

QAston via Digitalmars-d digitalmars-d at puremagic.com
Mon Apr 25 14:21:12 PDT 2016


On Monday, 25 April 2016 at 17:52:58 UTC, Andrei Alexandrescu 
wrote:
> Idea #1: Detect and use CNF, print which clause failed
> ====
>
> CNF (https://en.wikipedia.org/wiki/Conjunctive_normal_form) is 
> a formula shape in Boolean logic that groups clauses into a 
> top-level conjunction.
>
> The compiler could detect and use when CNF is used (as in the 
> example above), and when printing the error message it only 
> shows the first failing conjunction, e.g.:
>
> /d935/f781.d(16): Error: template f781.find cannot deduce 
> function from argument types !()(NotARange, int), candidates 
> are:
> /d935/f781.d(3): f781.find(R, E)(R range, E elem) constraint 
> failed: isInputRange!NotARange
>
> This is quite a bit better - it turns out many constraints in 
> Phobos are rather complex, so this would improve many of them. 
> One other nice thing is no language change is necessary.

Improvement in the generic case is a must. I personally either 
comment out the constraint in the lib source (if I can) or 
recreate the predicate in a context where I actually can see the 
error message. That's tedious and makes me hate template 
constraints because for templated libraries the source is there 
anyway, I prefer to be given real error (which shows me the exact 
issue) rather than a mystery puzzle.

Could your proposal be extended with showing the evaluation for 
isInputRange!NotARange to see why it returns false for given 
type, i.e. to see that compiler error:
> Error: no property 'empty' for type 'NotARange'

So for example the error message could look like:
  /d935/f781.d(16): Error: template f781.find cannot deduce
  function from argument types !()(NotARange, int), candidates
  are:
  /d935/f781.d(3): f781.find(R, E)(R range, E elem) constraint
  failed: isInputRange!NotARange
     constraint stacktrace:
        std.range.primitives.isInputRange!NotARange
        boolean expression: is(typeof(
     (inout int = 0)
     {
         NotARange r = NotARange.init;     // can define a range 
object
         if (r.empty) {}   // can test for empty
         r.popFront();     // can invoke popFront()
         auto h = r.front; // can get the front of the range
     }));
       failed with error: no property 'empty' for type 'NotARange'


Btw. I see you've taken a focus on making D more usable. Probably 
teaching D to new people gave you some very needed perspective 
:P. Big thanks!



More information about the Digitalmars-d mailing list