The proposal is to extend template constraint from:

if(<expr>)
 to
if(<expr>; <message-expr>)

Where the <message-expr> is CTFE-able expression with type string.

The message-expr yields a hint string for compiler to show when instantiation failed instead of full expression that failed. It has to be CTFE-able even if template instantiation never actually fails.

The original full expression verbose behavior can be restored if desired with "verbose" compiler switch. "Verbose template instantiation failure switch" can be later be further enhanced to detect which sub-expressions are false for each candidate template.


Now how it should look like in messages.

Taking a motivating example from pull
https://github.com/D-Programming-Language/phobos/pull/1047
(though all of you have certainly seen far, far worse):

bug.d(11): Error: template std.range.chain does not match any function template declaration. Candidates are: std/range.d(2018): std.range.chain(Ranges...)(Ranges rs) if (Ranges.length > 0 && allSatisfy!(isInputRange, staticMap!(Unqual, Ranges)) && !is(CommonType!(staticMap!(ElementType, staticMap!(Unqual, Ranges))) == void)) bug.d(11): Error: template std.range.chain(Ranges...)(Ranges rs) if (Ranges.length > 0 && allSatisfy!(isInputRange, staticMap!(Unqual, Ranges)) && !is(CommonType!(staticMap!(ElementType, staticMap!(Unqual, Ranges))) == void)) cannot deduce template function from argument types !()(MapResult!(__lambda2, Foo[]),string)

First there is another sub-enhancement to remove constraints from the last message
Error: template XYZ <constraint *again* > cannot deduce ... from

as listing of candidates already shown them all.

Second and the actual point applied (message can be improved but in any case it should accurately & concisely describe the constraint):

std/range.d(2018): std.range.chain(Ranges...)(Ranges rs) accepts: Any number of Input Ranges all having a common type among types of their elements.
bug.d(11): Error: template std.range.chain(Ranges...)(Ranges rs)
cannot deduce template function from argument types !()(MapResult!(__lambda2, Foo[]),string)

where "accepts:" is compiler generated prefix and "Any number..." is a hint message.

What do you think?

--
Dmitry Olshansky

Reply via email to