DIP 1008 Preliminary Review Round 1

Jonathan M Davis via Digitalmars-d digitalmars-d at puremagic.com
Fri May 19 19:05:21 PDT 2017


On Friday, May 19, 2017 3:45:28 PM PDT Mike Parker via Digitalmars-d wrote:
> DIP 1008 is titled "Exceptions and @nogc".
>
> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1008.md
>
> All review-related feedback on and discussion of the DIP should
> occur in this thread. The review period will end at 11:59 PM ET
> on June 2 (3:59 AM GMT June 3), or when I make a post declaring
> it complete.
>
> At the end of Round 1, if further review is deemed necessary, the
> DIP will be scheduled for another round. Otherwise, it will be
> queued for the formal review and evaluation by the language
> authors.
>
> Extensive discussion of this DIP has already taken place in two
> threads, both linked from the document. You may find it
> beneficial to skim through those threads before posting any
> feedback here.
>
> Thanks in advance to all who participate.

Overall, I think that this is a decent proposal for making exceptions @nogc
- and exceptions are definitely one of the few things that prevents code 
that
really should be @nogc from being @nogc. However, I do have two objections:

1. I thought that we were going to come up with a general solution for
ref-counted classes, not something for just exceptions. If that's the case,
then this makes a lot less sense. However, that being said, if this solution
can be transparently transitioned to a more general ref-counting solution,
then this is probably a good stop-gap solution (and if we can't get
ref-counted classes for some reason, then at least we'd have it for
exceptions).

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 at foo.d(20): no message
----------------
??:? _Dmain [0xd0d473ce]
??:? _D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFNlZv 
[0xd0d526db]
??:? scope void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).tryExec(scope void delegate()) [0xd0d52607]
??:? scope void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).runAll() [0xd0d52684]
??:? scope void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).tryExec(scope void delegate()) [0xd0d52607]
??:? _d_run_main [0xd0d52577]
??:? main [0xd0d5040b]
??:? __libc_start_main [0xf798a3f0]

toString wasn't used anywhere. toString would only be used if the exception
were caught and printed, e.g.

void main()
{
    import std.stdio;
    writeln(new E(42));
}

would print

The value was 42

whereas without the toString override, it would print

foo.E at foo.d(15): no message

So, as is stands, we need to pass strings to exception constructors, and if
we want those messsages to be informative, they cannot be string literals
and thus have to be GC-allocated if you don't want to risk memory leaks or
accessing memory that's no longer valid. And Walter's proposal does nothing
to fix that, so even with his proposal, it's not going to work well to have
code that throws exceptions be @nogc and have the error messages be useful.

What we would probably need would be to change msg is a function which
generates a message so that derived classes can override that rather than
passing a message string. Then at least the allocation of the string would
just happen when the exception was printed. And if it's okay to make getting
the exception @system, then it could even return a const(char)[] to a member
variable (be it a static array or a string) and potentially avoid allocating
altogether. Alternatively, if we're willing to have only one output range
type work with it (so that the function can be virtual), then we could
replace msg with a function that took an output range.

Regardless, with how exceptions are currently constructed, I don't think
that Walter's proposal goes far enough to actually fix the problem with
@nogc and exceptions, even if it does solve a critical piece of the problem.

- Jonathan M Davis



More information about the Digitalmars-d mailing list