A proposal for better template constraint error reporting.

Simen Kjaeraas simen.kjaras at gmail.com
Wed Oct 26 11:25:28 PDT 2011


On Wed, 26 Oct 2011 17:34:09 +0200, Gor Gyolchanyan  
<gor.f.gyolchanyan at gmail.com> wrote:

> This idea is still raw, so don't expect me to be able to answer to all
> your question. This is just a general direction in which we could move
> to improve the error reports, that occur when templates can't be
> instantiated.
> What if one could add ddoc comments to parts of the constraint, so
> that both ddoc generator could output them in a neat way and the
> compiler would use them to report errors:
>
> /// Define a state machine transition types.
> template transition(ActionType)
> 	if
> 	{
> 		/// Must be a callable type.
> 		isCallable!ActionType &&
> 		/// Must return a state.
> 		is(ReturnType!ActionType : State) &&
> 		/// Must take exactly two parameters.
> 		ParameterTypeTuple!(ActionType).length == 2 &&
> 		/// The first parameter must be an event.
> 		is(ParameterTypeTuple!(ActionType)[0] : Event) &&
> 		/// The second parameter must be a state.
> 		is(ParameterTypeTuple!(ActionType)[1] : State);
> 	)
> {
> 	alias ParameterTypeTuple!(ActionType)[1] FromState;
> 	alias ReturnType!ActionType ToState;
> 	alias ParameterTypeTuple!(ActionType)[0] Event;
> }
>
> The ddoc comments, preceding parts of template constraints would be
> used to specify why exactly did the template fail to instantiate, for
> example:
>
> Error: Cannot instantiate template demo01.transition(ActionType)
> because "Must return a state." constraint is not satisfied.
> Writing specifications of the template with all different version of
> incorrect constraints just to static assert(0) it is too tedious to do
> every time.

As always with this type of proposal, the case of multiple non-matching
templates seems not to have been considered. Given:

template foo(T) if (
     /// T must be an integer.
     is(T : long)) {}
template foo(T) if (
     /// T must be a string of some kind.
     isSomeString!T) {}
template foo(T) if (
     /// T must be an input range.
     isInputRange!T) {}

Which template's error messages should be shown? All of them, preceded
by the template definition? e.g:

bar.d(17): Error: template instance foo!(float) does not match any  
template declaration
   bar.d(5): template instance foo(T) if (is(T : long)) error instantiating
     bar.d(6): T must be an integer.
   bar.d(7): template instance foo(T) if (isSomeString!T) error  
instantiating
     bar.d(8): T must be a string of some kind.
   bar.d(79): template instance foo(T) if (isInputRange!T) error  
instantiating
     bar.d(10): T must be an input range.


I was gonna say this would bring problems with more complex constraints,
but after a brief look through Phobos, I have seen that most (~90%) of
constraints seem to be a single condition, with 2 making up the
majority of the remaining, and only one place have I found a constraint
with 3 conditions.

The reason for this is that it's often factored out to a separate
template or function, which helps some, but would perhaps reduce the
helpfulness of the error messages here proposed.

-- 
   Simen


More information about the Digitalmars-d mailing list