On Friday, 23 July 2021 at 20:24:02 UTC, Jim wrote:
Hello,

I've been playing with D and trying to understand how to work with @nogc. I must be doing something wrong, because even though I tagged the destructor for my class `@nogc`, I'm getting the following error: `.\min.d(27): Error: "@nogc" function "D main" cannot call non-@nogc function "object.destroy!(true, TestClass).destroy`

[...]
What is the problem here? Should I not call `destroy`? If so,

`destroy()` uses the runtime types informations to detect the most derived destructor (as you might cast from `TestClass` to least specialized, i.e `Object`). The type infos for classes stores the destructor in form of a function pointer that has not `@nogc` as part of its attributes.

what should I call instead?

get rid of `destroy()` and instead use your own allocator, virtual constructor (instead of `this(){}`) and virtual destructor (instead of `~this(){}`) in a base class.

e.g

```d
class Base
{
    static auto make(T : Base, Args...)(Args args)
    {
        auto size = __traits(classInstanceSize, T);
        auto memory = malloc(size)[0..size];
        T t = emplace!(T)(memory);
        t.construct(args); // call the most derived
        return t;
    }

    void construct() @nogc
    {
        printf("Base constructor called\n");
    }

    void destruct() @nogc
    {
        printf("Base destructor called\n");
        free(cast(void*) this);
    }
}

class Derived : Base
{
    override void construct() @nogc
    {
        super.construct(); // construct from base to most derived
        printf("Derived constructor called\n");
    }

    override void destruct() @nogc
    {
        printf("Derived destructor called\n");
        super.destruct(); // destruct from derived to base
                          // finishing with the deallocation
    }
}

void main(string[] args) @nogc
{
    Base b = Base.make!(Derived);
    b.destruct();
}
```

things get called correctly

Base constructor called
Derived constructor called
Derived destructor called
Base destructor called

That bypasses the runtime mechanism for classes construction and destruction. But `new` and `destroy` must not be called anymore, you must get stick with your own system.

Reply via email to