> Object.~this not being @nogc is severely limiting @nogc applicability
I agree.
There's two main reasons for the problem:
1/ OOP nature. One may call `destroy()` from an instance that's casted to a base type
2/ (the biggest issue IMO) destructors are not called by inheritance (like `super()` for constructors). destructors are found, from the most derived to the base using the `TypeInfo_Class` of each generation (indeed in `rt_finalize2()`). The TI just stores a pointer to a `void function()` and not to a `@nogc void function()`.
A workaround (that works since i currently use it) is not to use `destroy()` but create your own equivalent, templatized, able to infer `@nogc`. To solve the first issue you have to assume that the instance that passed to the custom `destroy()` function is the most derived (i.e the traits to get `__xdtor` doesn't return an ancestor `__xdtor`). Then to solve the second issue the `__xdtor` in the ancestors must be called by inheritance, which can be done by mixing a template at each generation.
There would also be the idea of an `@assumenogc` attribute. I remember that someone else needed it for the `IAllocator` interface.
Comment #2 by Marco.Leise — 2017-04-07T16:13:42Z
A previous bug report about rt_finalize and @nogc is issue 15246. It takes a look from a different angle, but boils down to the same fundamental issues.
Points 1/ (OOP nature) and 2/ (non-inheritance of ~this) from my previous commentator are also discussed there and I gave an example of an "OOP nature" case that I would like to cross post here for illustration purposes...
Quote:
If we did in fact have virtual destructors like C++, the general rule with inheritance applies: The derived thing must be usable everywhere the base class is used. That disallows the removal of attributes on virtual function overrides:
class C {
~this() @safe
}
class D {
override ~this(); // @system
}
void foo(C c) @safe
{
// Destroying D is unsafe, but we can't statically check,
// because for all we know it is at least a C.
destroy(c);
}
void main()
{
foo(new D);
}
Comment #3 by simen.kjaras — 2018-02-07T12:51:17Z
*** This issue has been marked as a duplicate of issue 15246 ***