Comment #0 by andrej.mitrovich — 2012-11-10T06:07:14Z
Currently __traits(compiles) simply checks whether an expression is compilable and returns true or false.
But it would be extremely useful if we had another trait which instead of returning true/false, it returned the error message (if any).
Consider the case of the msgpack serialization library. It currently does a check on whether a special serialization method is invokable on an object, e.g.:
/** Somewhere in the "Packer" class of the library */
T object;
static if (__traits(compiles, { T t; t.toMsgpack(this_); })) {
{
}
else // use library serialization routine
{
}
The problem here is if `toMsgpack` fails to instantiate (the library expects it to be a templated function), you won't notice it because the library just picks an internal routine for serialization as an alternative.
Here's a limited form of improvement we can already do right now (OT: I'm making a pull for this):
static if (hasToMsgpack!T) // first check if templated method exists
{
static if (__traits(compiles, { T t; t.toMsgpack(this); })) {
object.toMsgpack(this, withFieldName_);
} else {
static assert(0, "Couldn't invoke method 'toMsgpack' on type '" ~ Unqual!T.stringof ~ "'"); // print error on failed instantiation
}
} else { // internal routine
}
So now if your templated `toMsgpack` routine fails to instantiate you will get an informative error:
msgpack.d(822): Error: static assert "Couldn't invoke method 'toMsgpack' on type 'Struct'"
But, imagine if we had a way to extract the error message too. Then we could improve things even more:
static if (hasToMsgpack!T) // first check if templated method exists
{
static if (__traits(compiles, { T t; t.toMsgpack(this); })) {
object.toMsgpack(this, withFieldName_);
} else {
enum string errorMsg = __traits(errorMsg, { T t; t.toMsgpack(this); });
static assert(0, "Error instantiating 'toMsgpack' on type '" ~ Unqual!T.stringof ~ "'\n" ~ errorMsg);
}
} else {
}
So let's say you've had a wrongly written template:
struct Struct
{
void toMsgpack()(int)
{
}
}
The error could then be:
static assert "Error instantiating 'toMsgpack' on type 'Struct'
Error: function t.toMsgpack (int _param_0) is not callable using argument types (Packer)"
It's a major improvement over a generic message that you would have to explicitly write in a static assert.
Comment #1 by code — 2012-11-10T06:21:02Z
Just put the actual piece of code in the "else" branch and let the compiler emit the error for it?
Comment #2 by andrej.mitrovich — 2012-11-10T06:42:35Z
(In reply to comment #1)
> Just put the actual piece of code in the "else" branch and let the compiler
> emit the error for it?
Yeah that went pass me without even thinking. :)
It would still be nice to get the message so you can "decorate" it in a certain way.
Comment #3 by dlang-bugzilla — 2014-03-07T14:37:21Z
One potential issue is that this allows people to write code that parses error messages, then get angry at us for breaking their code by improving the error messages.