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.

Reply via email to