Bug 8992 – __traits(compileError)

Status
RESOLVED
Resolution
WONTFIX
Severity
enhancement
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-11-10T06:07:00Z
Last change time
2014-03-07T14:37:21Z
Assigned to
nobody
Creator
andrej.mitrovich

Comments

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.