Just recently running into some problems where deeply nested inside some library code, a static assert triggers. Of course, the static assert doesn't give any context with which it was called from my code.
And the compiler helpfully says something like (names changed to protect the proprietary):
somelibrary.d(263,16): instantiated from here: `foo!(Json[string])`
somelibrary.d(286,25): instantiated from here: `bar!(Json[string])`
somelibrary.d(204,16): instantiated from here: `baz!(Json)`
somelibrary.d(263,16): ... (1 instantiations, -v to show) ...
OK, so it stopped telling me useful information. And on top of that, the information isn't always enough to determine the cause, because in one of these instantiations, there's probably a static foreach, where I don't know which element being looped over is actually the cause.
If this was runtime I'd do something like:
scope(failure) writeln("Context: ", relevant, info);
And then when the exception is thrown, I can see some context. But I can't do that at compile time.
What I've done instead is:
static if(!__traits(compiles, entireLineOfCode)) pragma(msg, "Context: ", relevant, info);
entireLineOfCode;
Which is OK, but the place where I might want to print the context might not be for just one line of code, you might have to repeat an entire mess of stuff. And I was thinking, wouldn't it be cool to just do something like:
static scope(failure) pragma(msg, stuff);
Then, no matter what the context, or where it's failing, I can ensure that on a failure to compile, I can tease out some debug info at the relevant spot.
another possible syntax is something like:
pragma(msgOnFailure, stuff);
Which might even be gagged if the compiler isn't actually failing (i.e. this is inside a __traits(compiles)
)
Does this (or something like it) make sense?
-Steve