On Saturday, 20 May 2017 at 02:05:21 UTC, Jonathan M Davis wrote:
2. This really isn't going to fix the @nogc problem with
exceptions without either seriously overhauling how exceptions
are generated and printed or by having less informative error
messages. The problem is with how exception messages are
generated. They take a string, and that pretty much means that
either they're given a string literal (which can be @nogc but
does not allow for customizing the error message with stuff
like what the bad input was), or they're given a constructed
string (usually by using format) - and that can't be @nogc.
And you can't even create an alternate constructor to get
around the problem. Everything relies on the msg member which
is set by the constructor. Code that wants the message accesses
msg directly, and when the exception is printed when it isn't
caught, it's msg that is used. Not even overiding toString gets
around the issue. For instance, this code
class E : Exception
{
this(int i, string file = __FILE__, size_t line = __LINE__)
{
super("no message", file, line);
_i = i;
}
override string toString()
{
import std.format;
return format("The value was %s", _i);
}
int _i;
}
void main()
{
throw new E(42);
}
prints
foo.E@foo.d(20): no message
[...]
---
class E : Exception
{
this(int i, string file = __FILE__, size_t line = __LINE__)
{
super("no message", file, line);
_i = i;
}
override void toString(scope void delegate(in char[]) sink)
const
{
import std.format;
sink(format("The value was %s", _i));
}
int _i;
}
void main()
{
throw new E(42);
}
---
prints "The value was 42".
Personally, I use a string literal for msg in the constructor,
add some value members to the exception, and then override the
above toString.