On Wednesday, 21 March 2018 at 08:49:11 UTC, Mike Franklin wrote:
Step 1.  Make `emplace` @nogc
So we need to attribute `std.conv.emplace` as @nogc.

No, do not do that! `emplace` is ALREADY `@nogc` when given appropriate arguments. Adding the explicit annotation will limit its flexibility without enabling any new uses.

This compiles right now:

---
import std.conv;

class Foo {
        this() @nogc {}
}

@nogc void main() {
        char[__traits(classInstanceSize, Foo)] buffer;
        emplace!Foo(buffer[]);
}
---


`emplace` is `@nogc` if the constructor it calls is `@nogc`.



The real bug with nogc and things like emplace are the error messages. They should tell you the item in the call chain where @nogc is NOT inferred. So if the ctor there was not annotated right now it says:

Error: @nogc function D main cannot call non-@nogc function std.conv.emplace!(Foo).emplace

Well, it should say:

Error: @nogc function D main cannot call non-@nogc function std.conv.emplace!(Foo).emplace >> emplace was not inferred because it calls non-@nogc function `Foo.this()`


That supplemental bit with the >> indicates the ACTUAL reason nogc failed. Change that and the rest of the call tree becomes nogc automatically.

I seem to remember filing this to bugzilla sometime but bugzilla search is so unbelievably bad I can never find anything on there so idk for sure.

But this error message change would be my #1 request for nogc. It'd keep others from chasing false leads.


Step 2. Make `destroy` @nogc
`destroy` simply calls `rt_finalize` in the runtime, at least for classes. I declared it as `@nogc` in the code above, but that's a cheat, though I think `rt_finalize` can be made `@nogc` in the runtime.

This cannot be proven at compile time since it calls destructors based on a dynamic type which may or may not keep the nogc promise.

Of course, dtors that gc allocate are usually broken anyway... but it isn't a compile time guarantee in the current language and a library change cannot fix that alone.

Reply via email to