Feature Idea: Error Message Replacing

Hi,

This is a feature idea I just came up with. I have no concrete plans to
implement this, but I thought I'd post it to the list to see if others
like it as well, and to preserve it for future reference.

I'm currently working on a Boost library, and in the compile errors this
shows up:

error: invalid use of incomplete type ‘struct
boost::property_tree::path_of<boost::any>’

Because I've written this library, I know that this error really means,
"You haven't specialized the path_of struct for that template argument
you're trying to use, but this is a prerequisite." If I were a user of
the library, I'd have no clue.
I think there should be a way for the library author to communicate this
knowledge to the user. I'm imagining something like this:

--- File: boost/property_tree/ptree.hpp (the library's main include) ---
#pragma clang error_catalog "boost/property_tree/property_tree.en.ec"

// Users have to specialize this
template <typename Key> struct path_of;

--- File: boost/property_tree/property_tree.en.ec (pseudo-syntax) ---
match "invalid use of incomplete type 'struct
boost::property_tree::path_of<{T}>'"
replacement "you need to specialize 'boost::property_tree::path_of' for
'$T' in order to use it as a property tree key"

Then, when I do

boost::basic_ptree<boost::any, int> pt;

I get the error

error: you need to specialize 'boost::property_tree::path_of' for
'boost::any' in order to use it as a property tree key

Error catalogs would be looked up either in the include path or some
separate lookup path; I would prefer the include path because it makes
using error catalogs "just work" for the library user. Error catalogs
are cumulative, i.e. you can have any number of error_catalog pragmas in
a translation unit.

Comments? With C++0x concepts, the need for this is obviously smaller
(my example is a result of a pseudo-concept emulation), but I think it
could still be useful.

Sebastian

To an extent this is similar to an issue I would like to solve in C++0x with another standard attribute (although I suspect the time for even limited proposals is long past). Essentially, there is a problem that template struct path_of needs to be declared purely as a means to define [partial] specializations - the primary template itself is never designed to be instantiated. There are templates like this is in the standard library (std::function, for instance) and it would be really nice to add an attribute that says 'you must always provide a specialization for this template'.

  // Users have to specialize this
  template <typename Key> struct path_of [[not_defined]];

Now your idea here goes further with linking the lack-of-specialization to a specific library use for even better error messages - I'm not sure how my simple attribute could cover that.

AlisdairM

Don't concept maps cleanly provide the desired functionality for both of these cases? (Not that they're much help yet.)

— Gordon

Hi Sebastian,

This is a feature idea I just came up with. I have no concrete plans to
implement this, but I thought I'd post it to the list to see if others
like it as well, and to preserve it for future reference.

I'm currently working on a Boost library, and in the compile errors this
shows up:

error: invalid use of incomplete type ‘struct
boost::property_tree::path_of<boost::any>’

Because I've written this library, I know that this error really means,
"You haven't specialized the path_of struct for that template argument
you're trying to use, but this is a prerequisite." If I were a user of
the library, I'd have no clue.
I think there should be a way for the library author to communicate this
knowledge to the user.

What do you need to do that static_assert doesn't already do?

I'm imagining something like this:

--- File: boost/property_tree/ptree.hpp (the library's main include) ---
#pragma clang error_catalog "boost/property_tree/property_tree.en.ec"

// Users have to specialize this
template <typename Key> struct path_of;

--- File: boost/property_tree/property_tree.en.ec (pseudo-syntax) ---
match "invalid use of incomplete type 'struct
boost::property_tree::path_of<{T}>'"
replacement "you need to specialize 'boost::property_tree::path_of' for
'$T' in order to use it as a property tree key"

Isn't this going to be brittle, since the wording of error messages might change from one Clang release to another?

Then, when I do

boost::basic_ptree<boost::any, int> pt;

I get the error

error: you need to specialize 'boost::property_tree::path_of' for
'boost::any' in order to use it as a property tree key

This is one cool thing that static_assert can't do , because you've captured the type via {T} and can now use that type in the reformatted error message. We could do the same kind of thing through an extension to static_assert:

   template<typename T>
   struct path_of {
     static_assert(always_false<T>::value, "you need to specialize 'boost::property_tree::path_of' for %0 in order to use it as a property tree key", T);
   };

A couple years back, I prototyped something like this for GCC, using some gross hacks in the G++ front end and a poor approximation of static_assert. The results looked promising, because the custom diagnostic can give much better information than the generic error message, especially if it can refer to your own instantiation.

  - Doug

Hi Sebastian,

This is a feature idea I just came up with. I have no concrete plans to
implement this, but I thought I'd post it to the list to see if others
like it as well, and to preserve it for future reference.

I'm currently working on a Boost library, and in the compile errors this
shows up:

error: invalid use of incomplete type ‘struct
boost::property_tree::path_of<boost::any>’

Because I've written this library, I know that this error really means,
"You haven't specialized the path_of struct for that template argument
you're trying to use, but this is a prerequisite." If I were a user of
the library, I'd have no clue.
I think there should be a way for the library author to communicate this
knowledge to the user.

What do you need to do that static_assert doesn't already do?

I'm imagining something like this:

--- File: boost/property_tree/ptree.hpp (the library's main include) ---
#pragma clang error_catalog "boost/property_tree/property_tree.en.ec"

// Users have to specialize this
template <typename Key> struct path_of;

--- File: boost/property_tree/property_tree.en.ec (pseudo-syntax) ---
match "invalid use of incomplete type 'struct
boost::property_tree::path_of<{T}>'"
replacement "you need to specialize 'boost::property_tree::path_of' for
'$T' in order to use it as a property tree key"

Isn't this going to be brittle, since the wording of error messages might change from one Clang release to another?

Then, when I do

boost::basic_ptree<boost::any, int> pt;

I get the error

error: you need to specialize 'boost::property_tree::path_of' for
'boost::any' in order to use it as a property tree key

This is one cool thing that static_assert can't do , because you've captured the type via {T} and can now use that type in the reformatted error message. We could do the same kind of thing through an extension to static_assert:

  template<typename T>
  struct path_of {
    static_assert(always_false<T>::value, "you need to specialize 'boost::property_tree::path_of' for %0 in order to use it as a property tree key", T);
  };

A couple years back, I prototyped something like this for GCC, using some gross hacks in the G++ front end and a poor approximation of static_assert. The results looked promising, because the custom diagnostic can give much better information than the generic error message, especially if it can refer to your own instantiation.

  - Doug

Douglas Gregor wrote:

Hi Sebastian,

Because I've written this library, I know that this error really means,
"You haven't specialized the path_of struct for that template argument
you're trying to use, but this is a prerequisite." If I were a user of
the library, I'd have no clue.
I think there should be a way for the library author to communicate this
knowledge to the user.

What do you need to do that static_assert doesn't already do?

I want to catch and explain arbitrary misuses of the library, beyond
those detectable by the type system. But I admit that static_assert +
concepts cover 95% of the use cases, so implementing this is probably
not worth it.

--- File: boost/property_tree/property_tree.en.ec (pseudo-syntax) ---
match "invalid use of incomplete type 'struct
boost::property_tree::path_of<{T}>'"
replacement "you need to specialize 'boost::property_tree::path_of' for
'$T' in order to use it as a property tree key"

Isn't this going to be brittle, since the wording of error messages
might change from one Clang release to another?

Yes. Part of working this out properly would be to devise a way of
making it less brittle.

Then, when I do

boost::basic_ptree<boost::any, int> pt;

I get the error

error: you need to specialize 'boost::property_tree::path_of' for
'boost::any' in order to use it as a property tree key

This is one cool thing that static_assert can't do , because you've
captured the type via {T} and can now use that type in the reformatted
error message. We could do the same kind of thing through an extension
to static_assert:

  template<typename T>
  struct path_of {
    static_assert(always_false<T>::value, "you need to specialize
'boost::property_tree::path_of' for %0 in order to use it as a
property tree key", T);
  };

A couple years back, I prototyped something like this for GCC, using
some gross hacks in the G++ front end and a poor approximation of
static_assert. The results looked promising, because the custom
diagnostic can give much better information than the generic error
message, especially if it can refer to your own instantiation.

This is awesome. We should totally forget about my proposal and
implement this instead.

Sebastian

We could do the same kind of thing through an extension
to static_assert:

template<typename T>
struct path_of {
   static_assert(always_false<T>::value, "you need to specialize
'boost::property_tree::path_of' for %0 in order to use it as a
property tree key", T);
};

A couple years back, I prototyped something like this for GCC, using
some gross hacks in the G++ front end and a poor approximation of
static_assert. The results looked promising, because the custom
diagnostic can give much better information than the generic error
message, especially if it can refer to your own instantiation.

This is awesome. We should totally forget about my proposal and
implement this instead.

:slight_smile:

   - Doug