Jump to page: 1 24  
Page
Thread overview
[Issue 15246] Destructor inheritance doesn't inherit attributes properly
Oct 25, 2015
ag0aep6g@gmail.com
Oct 26, 2015
Marco Leise
Oct 26, 2015
Marco Leise
Oct 27, 2015
Marco Leise
Oct 27, 2015
Marco Leise
Oct 27, 2015
Marco Leise
Oct 27, 2015
Marco Leise
Apr 21, 2017
Rainer Schuetze
May 21, 2017
Stanislav Blinov
Feb 07, 2018
Simen Kjaeraas
Feb 07, 2018
Simen Kjaeraas
Apr 23, 2018
Simen Kjaeraas
May 11, 2018
ponce
Jun 09, 2020
timon.gehr@gmx.ch
Jun 09, 2020
timon.gehr@gmx.ch
Oct 13, 2022
RazvanN
Dec 17, 2022
Iain Buclaw
October 25, 2015
https://issues.dlang.org/show_bug.cgi?id=15246

ag0aep6g@gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |accepts-invalid
                 CC|                            |ag0aep6g@gmail.com
           Severity|enhancement                 |normal

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

Marco Leise <Marco.Leise@gmx.de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |Marco.Leise@gmx.de

--- Comment #1 from Marco Leise <Marco.Leise@gmx.de> ---
You are assuming that destructors are inherited and there is an implicit super-call, but they are actually chained and called one after another from outer to inner. Under the current language semantics this bug report is invalid.

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

--- Comment #2 from Marco Leise <Marco.Leise@gmx.de> ---
Here is the loop that iterates the inheritance chain from up to Object and
calls destructors (if defined):
https://github.com/D-Programming-Language/druntime/blob/v2.069.0-b2/src/rt/lifetime.d#L1366

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

--- Comment #3 from Andrei Alexandrescu <andrei@erdani.com> ---
(In reply to Marco Leise from comment #1)
> You are assuming that destructors are inherited and there is an implicit super-call, but they are actually chained and called one after another from outer to inner. Under the current language semantics this bug report is invalid.

I agree I am using terminology loosely; newly introduced destructors don't only override the existing ones, they also call them. But I don't see how that makes the bug report invalid.

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

--- Comment #4 from Marco Leise <Marco.Leise@gmx.de> ---
The destructors do *neither* inherit *nor* call their parent destructors. Not as a matter of terminology, but because in D they are not called recursively, but in sequence, starting from the runtime type's dtor and working its way up the inheritance chain. Take a look at the druntime source I linked above and you will understand what happens.

To make the bug report valid we would have to introduce destructor inheritance to the language to begin with. Right now the only functions affected by the destructor attributes would be the attribute-less external(C) functions `rt_finalize` and `rt_finalize2`. (In client code we call `rt_finalize` as `destroy(Object obj)` for deterministic object destruction).

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

--- Comment #5 from Andrei Alexandrescu <andrei@erdani.com> ---
(In reply to Marco Leise from comment #4)
> The destructors do *neither* inherit *nor* call their parent destructors. Not as a matter of terminology, but because in D they are not called recursively, but in sequence, starting from the runtime type's dtor and working its way up the inheritance chain. Take a look at the druntime source I linked above and you will understand what happens.
> 
> To make the bug report valid we would have to introduce destructor inheritance to the language to begin with. Right now the only functions affected by the destructor attributes would be the attribute-less external(C) functions `rt_finalize` and `rt_finalize2`. (In client code we call `rt_finalize` as `destroy(Object obj)` for deterministic object destruction).

I understand what happens technically (each dtor is distinct, and code external to the destructor calls them all).

What happens conceptually is that destructors in derived classes both override and call destructors in base classes. There is no need to change the language to make the bug report valid. Destructors must typecheck as if they override and call the base class destructors.

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

--- Comment #6 from Marco Leise <Marco.Leise@gmx.de> ---
I'd agree with you if this was all not observable, but your change causes friction that I object against. It should be either inheritance all the way or just sequential calls as right now. Otherwise destructors will be perceived as inheriting while type-checking and as stand-alone when called directly. To illustrate this:

    import core.stdc.stdio;
    void main()
    {
        // Get a vanilla 'Ext' object without calling
        // constructors and spoiling the output.
        void[__traits(classInstanceSize, Ext)] buf = void;
        buf[] = typeid(Ext).init[];
        // Show constructor/destructor semantics.
        Ext ext = cast(Ext) buf.ptr;
        ext.__ctor();
        ext.__dtor();
    }
    class Base {
        void* v;
        this() { printf("Base ctor\n"); }
        ~this() { printf("Base dtor\n"); } // never called
    }
    class Ext : Base {
        this() { printf("Ext ctor\n"); }
        ~this() @nogc nothrow { printf("Ext dtor\n"); }
    }

Prints:
  Base ctor
  Ext ctor
  Ext dtor

In particular in this example with D's semantics it is correct to have Ext's destructor be @nogc nothrow while the Base destructor is not. It may be surprising depending on programming language background, but at least it is consistently implemented as far as I can tell.

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

--- Comment #7 from Andrei Alexandrescu <andrei@erdani.com> ---
@mleise that is surprising. I assumed calling __dtor also invokes the base destructors.  What is the canonical way to destroy a D class properly?

(This bug report stands.)

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

--- Comment #8 from Marco Leise <Marco.Leise@gmx.de> ---
We "finalize" them through the helper function `rt_finalize` mentioned earlier, which calls the __dtor's in sequence and is the only place that also handles destruction of the hidden "monitor" field if it was used. It is wrapped in object.d as:

    void destroy(T)(T obj) if (is(T == class))
    {
        rt_finalize(cast(void*)obj);
    }

destroy() complete object finalization + memory reinitialized to .init
__xdtor   same as __dtor + destroys any RAII members
__dtor    the ~this() function as defined in the source
(That's how I remember it. May be inaccurate.)

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

--- Comment #9 from Andrei Alexandrescu <andrei@erdani.com> ---
That's quite the bummer because rt_finalize in all likelihood doesn't know anything about attributes.

--
« First   ‹ Prev
1 2 3 4