Here's another thing that should be allowed that doesn't depend on optimizations:

Any code path in a @nogc function that is guaranteed to abort the program should be exempt from @nogc enforcement. This includes assert(0) and throwing an Error.

Take std.exception.assumeWontThrow() as an example:

T assumeWontThrow(T)(lazy T expr,
                     string msg = null,
                     string file = __FILE__,
                     size_t line = __LINE__) nothrow
{
    try
    {
        return expr;
    }
    catch(Exception e)
    {
        immutable tail = msg.empty ? "." : ": " ~ msg;
throw new AssertError("assumeWontThrow failed: Expression did throw" ~
                              tail, file, line);
    }
}

Currently, this cannot be @nogc, because it uses `new` and `~`. However, this only happens in preparation to throwing the AssertError, which in turn causes the program to abort. I guess in this situation, it's ok to allocate on the GC heap.

With my proposed rule, assumeWontThrow can be deduced to be @nogc iff expr is @nogc. This allows more functions to be @nogc.

Reply via email to