DIP 1008 Preliminary Review Round 1

Atila Neves via Digitalmars-d digitalmars-d at puremagic.com
Thu May 25 16:54:34 PDT 2017


On Friday, 19 May 2017 at 15:45:28 UTC, Mike Parker 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.
>
> Destroy!

As many others, I dislike special-casing "throw new" and enough 
has been said about that.

I also don't like adding hooks to druntime, or that by doing so 
the allocation strategy is baked in (but I guess only when using 
the `new` operator so there's that).

I think maybe the problem isn't with `throw` but with `catch`. 
What if instead we make it so that:

catch(scope T ex) { /*...*/; }

Means:

catch(scope T ex) { /*...*/; ex.__dtor; }


That way whoever is throwing the exception allocates however he 
or she sees fit and the memory is handled by the class's 
destructor. Sort of proof of concept using malloc (if I did this 
for real I'd use std.allocator):

class MallocException: Exception {

     char* buffer;
     size_t length;

     // has to be public or `emplace` won't compile
     this(string msg) @nogc {
         import core.stdc.stdlib: malloc;
         length = msg.length;
         buffer = cast(char*)malloc(length);
         buffer[0 .. length] = msg[];
         super(cast(string)buffer[0 .. length]);
     }

     ~this() @nogc {
         import core.stdc.stdlib: free;
         free(buffer);
         free(cast(void*)this);
     }

     static MallocException create(string msg) @nogc {
         import core.stdc.stdlib: malloc;
         import std.conv: emplace;
         enum size = __traits(classInstanceSize, MallocException);
         auto buf = malloc(size);
         return emplace!MallocException(buf[0 .. size], msg);
     }
}

void main() @nogc {
     try {
         import core.stdc.stdlib: malloc;
         throw MallocException.create("oops");
     } catch(MallocException ex) {
         ex.__dtor;
     }
}

The code above works today, the annoying thing is having to 
invoke the destructor manually (and also knowing it's called 
`__dtor`).

This would however mean delaying making phobos @nogc since each 
`throw` site would have to be changed.

And if someone never remembers to catch by scope somewhere and is 
allocating memory themselves, well... use the GC, Luke.

Atila


More information about the Digitalmars-d mailing list