Truly @nogc Exceptions?

Atila Neves atila.neves at gmail.com
Fri Oct 19 23:34:01 UTC 2018


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 at 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.




More information about the Digitalmars-d mailing list