digitalmars.D.learn - Prettiful error messages with templates
- Simen Kjaeraas (43/43) May 04 2008 I'm currently using this somewhat verbose approach to template error =
- Lutger (45/45) May 05 2008 Not sure how this works in D2 and it doesn't solve the biggest problems ...
I'm currently using this somewhat verbose approach to template error = messages: debug { int opAdd(U, int line =3D __LINE__, string file =3D __FILE__)(U args)= { static if (__traits(compiles, somethingHere)) // check if this = template should have been instantiated at all { pragma(msg, "Failed instantiating template in file " ~ file ~ " o= n = line " ~ toString(line)); // for a more prettiful error message. Could = easily put this in the assert static assert(0); } // Do actual work here. Don't use line or file arguments. } } else { int opAdd(U)(U args) { // Do actual work here. } } Now, what are the problems with this approach? 1. It is rather verbose. 2. Code duplication. 3. Template bloat for the debug version. For every time + is used, a new= = instantiation is created. I have duplicated the code to avoid this in = release builds. 4. toString(int) is not CTFE-compatible. Good things: It gives exact error messages, telling the user what went wrong and wher= e. So, what do I want? limitation of the linker or compiler), I could avoid the code duplicatio= n, = so I guess that's the biggest problem. Any ideas? -- Simen
May 04 2008
Not sure how this works in D2 and it doesn't solve the biggest problems but here's a possible begin: char[] assertCompiles(uint line, char[] file, char[] code) { return `debug { static if (!__traits(compiles, ` ~ code ~ `))` `{` `pragma(msg, "Failed instantiating template in file ` ~ file ~ ` on line ` ~ ctfeToString(line) ~ `");` `static assert(false);` `}}`; } iirc I adapted ctfeToString from phobos' std.string: const char[10] digits = "0123456789"; /// 0..9 /// ditto char[] ctfeToString(ulong u) { char[] buffer; auto buflen = ulong.sizeof * 3; while (buflen--) buffer ~= ' '; int ndigits; ndigits = 0; if (u < 10) // Avoid storage allocation for simple stuff return digits[u .. u + 1]; else { while (u) { uint c = (u % 10) + '0'; u /= 10; ndigits++; buffer[buffer.length - ndigits] = cast(char)c; } return buffer[buffer.length - ndigits .. buffer.length].dup; } } it'll help a bit with the verbosity, used as: int opAdd(U, uint line = __LINE__, char[] file = __FILE__ ) (U args) { mixin( assertCompiles(line, file, code)); ... } Will you post back when you found some good solutions? Thanks. Good luck and happy hacking ;)
May 05 2008