On Thursday, 20 September 2018 at 12:48:13 UTC, Steven Schveighoffer wrote:
On 9/20/18 6:48 AM, Atila Neves wrote:
On Wednesday, 19 September 2018 at 21:16:00 UTC, Steven Schveighoffer wrote:
Given dip1008, we now can throw exceptions inside @nogc code! This is really cool, and helps make code that uses exceptions or errors @nogc. Except...

The mechanism to report what actually went wrong for an exception is a string passed to the exception during *construction*. Given that you likely want to make such an exception inside a @nogc function, you are limited to passing a compile-time-generated string (either a literal or one generated via CTFE).

<snip>

I expressed my concern for DIP1008 and the `msg` field when it was first announced. I think the fix is easy and a one line change to dmd. I also expressed this on that thread but was apparently ignored. What's the fix? Have the compiler insert a call to the exception's destructor at the end of the `catch(scope Exception)` block. That's it. The `msg` field is just a slice, point it to RAII managed memory and you're good to go.

Give me deterministic destruction of exceptions caught by scope when using dip1008 and I'll give you @nogc exception throwing immediately. I've even already written the code!

I thought it already did that?

Nope:

---------------
class MyException: Exception {
    static int numInstances;
    this(string msg) {
        super(msg);
        ++numInstances;
    }

    ~this() {
        --numInstances;
    }
}

void main() {
    assert(MyException.numInstances == 0);

    try
        throw new MyException("oops");
    catch(MyException _)
        assert(MyException.numInstances == 1);

    assert(MyException.numInstances == 0);
}
---------------

% dmd -dip1008 -run exception.d
core.exception.AssertError@exception.d(21): Assertion failure

How is the exception destroyed when dip1008 is enabled?

Apparently, it isn't. Which renders dip1008 pretty much useless since we could already use static immutable exceptions before.

But this means you still have to build msg when throwing the error/exception. It's not needed until you print it, and there's no reason anyway to make it allocate, even with RAII. For some reason D forces msg to be built, but it does't e.g. build the entire stack trace string before hand, or build the string that shows the exception class name or the file/line beforehand.


Allocating and building the string doesn't bother me - in all of my uses it's eventually going to get printed (which means the string needed to be built), and the exceptional path can be slow, I don't mind.

But, one could always store a tuple of members in an exception class instead and only build the string on demand.

I just think it's easier with an RAII string.


Reply via email to