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.