D's Destructors are What Scott Meyers Warned Us About

sarn sarn at theartofmachinery.com
Sun May 27 22:27:52 UTC 2018


On Sunday, 27 May 2018 at 09:55:56 UTC, Mike Franklin wrote:
> TypeInfo has become my nemesis.  I've been trying to replace 
> runtime hooks that depend on TypeInfo with templates that can 
> get their information at compile-time, but I'm running into all 
> sorts of problems.  e.g. Did you know array.length can be set 
> in @safe nothrow pure code, but it lowers to runtime functions 
> that are neither @safe, nothrow, nor pure?

Ouch.

> Anyway, I'm getting better at modifying the compiler/runtime 
> interface.  If we can come up with a solution to this mess, and 
> I can understand it, I might be able to implement it.

I've been meaning to learn more about how the compiler/runtime 
interface works myself but still haven't got around it.  I'm 
probably going to learn a lot by looking at your PRs.

I've been thinking this through a bit, and here's what I've got 
so far:

At first I obviously wanted an all-round "just works" low-level 
interface for destroying objects.  But after looking at how 
people are using __dtor/__xdtor in real code, and looking at the 
PRs for destroy(), it's obvious that there's a lot of 
disagreement about what that means.  Let's leave that topic for 
now.

If we just focus on fixing classes, we can add, say, __vdtor (I 
really don't care much about the name, BTW).  This needs to be a 
normal virtual function in the vtable (preferably in a way that's 
compatible with C++ ABIs) that runs the user-defined destructor 
code, then recursively calls destructors for members and base 
classes.

The generation of __vdtor also needs a special case to make 
attributes work.  Something like "an empty destructor has 
attributes inferred like templated functions are, restricted by 
any of its bases".  For example, this needs to work:

extern(C++)
{

class Base
{
     // Virtual
     ~this() @nogc
     {
     }
}

class Derived
{
     // Not marked pure but is still @nogc
     // (NB: explicitly marking @nogc isn't needed in current 
language)
     override ~this() @nogc
     {
     }
}

class Derived2 : Derived
{
     override ~this() @nogc pure
     {
         // Marked pure, but still recurses to empty destructors 
in Derived and Base
     }
}

}

Right now __vdtor would need to be implemented with a thunk that 
wraps around __xdtor (like I implemented here: 
https://theartofmachinery.com/2018/05/27/cpp_classes_in_betterc.html).  But if __vdtor is implemented, the D runtime code can be simplified to use __vdtor for classes, then hopefully we can deprecate and remove __dtor and __xdtor for classes, and then __vdtor can become the native destructor implementation.


More information about the Digitalmars-d mailing list