October 27, 2015
https://issues.dlang.org/show_bug.cgi?id=15246

--- Comment #10 from Marco Leise <Marco.Leise@gmx.de> ---
Nope, in fact it is an extern(C) function, and I assume part of the druntime API that people replace when writing bare metal runtimes etc.

Since destructors don't need to inherit attributes for anything based on the current implementation, this bug report has no basis. If attributes were inherited, it would not solve any use case or problem. If you meant to streamline the language semantics with this, it was well meant, but actually adds to the cognitive load.

Or did you have some specific use case in mind, like being able to deterministically destroy objects in @safe functions? That's not going to happen either way. As it stands now, `destroy(obj)` and `rt_finalize`, which is neither @safe nor @nogc nor nothrow nor pure. And 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);
}

--
April 21, 2017
https://issues.dlang.org/show_bug.cgi?id=15246

Rainer Schuetze <r.sagitario@gmx.de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |r.sagitario@gmx.de

--- Comment #11 from Rainer Schuetze <r.sagitario@gmx.de> ---
See http://dlang.org/spec/class.html#destructors: "The destructor for the super class automatically gets called when the destructor ends. There is no way to call the super destructor explicitly."

I.e. the net effect of destructing an Object is the same as C++ virtual destructor. It doesn't really matter how it is implemented, and the usage of double underscores suggests that, too. Poking at the internals of __dtor, __xdtor or rt_finalize should not have an effect on the language definition.

Changing Andrei's example slightly with

void main() pure nothrow @safe @nogc {
    scope w = new Gadget;
}

compiles and generates the direct call to rt_finalize violating all the attributes of main (but throws a FinalizeError due to throwing an exception - this should only happen when called by the GC).

One option for keeping annotated class destructors useful without adding more attributes: when checking attributes of the destructor of the derived class, assume a trailing call to the base class destructor, but infer it's attributes from the code. If no code is available for inference only the explicit attributes are assumed (similar to declared (but not defined) functions in templates!).

--
May 21, 2017
https://issues.dlang.org/show_bug.cgi?id=15246

Stanislav Blinov <stanislav.blinov@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |stanislav.blinov@gmail.com

--- Comment #12 from Stanislav Blinov <stanislav.blinov@gmail.com> ---
I agree with Andrei and Rainer. It should not matter in what order the runtime
calls the destructors. If it does call them, it calls all of them. So the net
observable effect should be as if all of them are called.
User code is not expected to call dtors explicitly. While we *can* (and should
be able to) do that, it should not allow attributes to conflict.
That means the strictest attribute set "wins", and derived class should not be
allowed to loosen the restrictions.

Effectively, the first class in the hierarchy to define a destructor has final authority over the dtor attributes, and no derived classes after that can define dtor with different attributes, or implicitly violate the attributes (via members). This is not covariance, we're not looking at a virtual call.

If the class doesn't explicitly define a dtor, it should be inferred from non-reference members (structs, fixed-size arrays, etc). As of right now, members don't have any effect on the class dtor:

struct S { ~this() @nogc {} }

class A { S s; } // compiles
class B { S s;  ~this() {} } // compiles, but shouldn't

For a, ~this() @nogc should be inferred.
For B, it should be a compile-time error.

There should be a strict agreement on dtors throughout the hierarchy and within each definition. Otherwise, we're free to violate attributes however we please. For example, this also compiles (note, these are structs, not classes):

struct A { ~this() {} }
struct B { A a; ~this() @nogc {} }

But this function will not:

void snafu(B b) @nogc {}

Note the error message:
Error: @nogc function snafu cannot call non-@nogc destructor B.~this.

What??? So *there* it catches that B's dtor is not really @nogc!

While B's dtor in itself might not make any GC calls, destruction of B implies destruction of all members. A's dtor is not @nogc, and so B's shouldn't be @nogc.

Members that are reference types (classes, interfaces, dynamic arrays...) should be excluded from that check, as user code is expected to explicitly destruct them by calling the destroy() function, and so if users want to destruct them with the object, they'd have to define a destructor, which in turn will have to be checked against the destroy() calls made within:

class A { ~this() {} }

class B { A a; ~this() @nogc {} } // fine, a leaks (i.e. reliance on GC)
class C { A a; ~this() @nogc { destroy(a); } } // error, destroy() is not @nogc

class D : B { ~this() {} } // error, base dtor is @nogc

struct S { ~this() @nogc {} }

class E : A { S s; }  // error, E's dtor has to be @nogc, but A's dtor isn't

class F { ~this() @nogc {} }
class G { S s; F f; ~this() @nogc { destroy(f); } } // fine, S dtor is @nogc,
destroy(f) is inferred @nogc

Same goes for safety, purity, nothrow, etc:

class A { ~this() {} }

class B { A a; ~this() nothrow {} } // fine
class C { A a; ~this() { destroy(a); } } //error, destroy() may throw

class D { ~this() @safe pure {} }
class E : D { ~this() pure {} } // error, D.~this is @safe, E.~this should also
be @safe

...and so on.

We *could* allow covariance between @safe and @trusted, but once any of those are in the hierarchy, @system dtors should be out the window.

rt_finalize does not need to change. destroy(obj) should statically typecheck the hierarchy from obj up, cast a pointer to rt_finalize to a function with appropriate set of attibutes, and call it. But we need to make sure that rt_finalize doesn't perform any GC calls (it doesn't look like it does, the monitor is not a GC-allocated object).

The only special cases here are if destroy(obj) is called with an Object (or an
interface, which just casts to Object anyway). For these, it looks like
destroy() should treat Object as if it was a class with this dtor:

~this() @system {}

If destroy() is called with an actual user-defined class, Object should be
ignored.

All of the above should ensure that destroy(obj) can safely infer attributes
from the hierarchy [typeof(obj), Object), as anything derived from typeof(obj)
is not allowed to violate those attributes.

--
May 22, 2017
https://issues.dlang.org/show_bug.cgi?id=15246

greensunny12@gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |greensunny12@gmail.com

--
February 07, 2018
https://issues.dlang.org/show_bug.cgi?id=15246

--- Comment #14 from Simen Kjaeraas <simen.kjaras@gmail.com> ---
*** Issue 17867 has been marked as a duplicate of this issue. ***

--
February 07, 2018
https://issues.dlang.org/show_bug.cgi?id=15246

Simen Kjaeraas <simen.kjaras@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |aliloko@gmail.com

--- Comment #15 from Simen Kjaeraas <simen.kjaras@gmail.com> ---
*** Issue 17297 has been marked as a duplicate of this issue. ***

--
April 23, 2018
https://issues.dlang.org/show_bug.cgi?id=15246

--- Comment #16 from Simen Kjaeraas <simen.kjaras@gmail.com> ---
*** Issue 17867 has been marked as a duplicate of this issue. ***

--
May 11, 2018
https://issues.dlang.org/show_bug.cgi?id=15246

alexanderheistermann@gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Blocks|                            |13972


Referenced Issues:

https://issues.dlang.org/show_bug.cgi?id=13972
[Issue 13972] Make scoped, Unique, and RefCounted @nogc
--
May 11, 2018
https://issues.dlang.org/show_bug.cgi?id=15246

--- Comment #17 from alexanderheistermann@gmail.com ---
This bug blocks certain Phobos functions from being @nogc as it involves the destroy function. I am bumping the importance of this to critical status, as the current workarounds I seen involves taking a sledge hammer approach, as it forces the compiler to assume @nogc.

Here an example of what I was referring to. https://www.auburnsounds.com/blog/2016-11-10_Running-D-without-its-runtime.html

--
May 11, 2018
https://issues.dlang.org/show_bug.cgi?id=15246

alexanderheistermann@gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Severity|normal                      |critical

--