On Tue, Feb 17, 2026 at 01:52:57PM -0800, Ali Çehreli via Digitalmars-d-learn wrote: > On 2/14/26 4:46 PM, H. S. Teoh wrote: > > On Sat, Feb 14, 2026 at 10:03:17PM +0000, Paul Backus via > > Digitalmars-d-learn wrote: > > > On Saturday, 14 February 2026 at 18:42:21 UTC, H. S. Teoh wrote: [...] > > > > Calling .destroy on a class object more than once may trigger UB. > > > > > > This is technically true, in the sense that calling any function > > > could conceivably trigger UB, but destructors *should* be > > > idempotent, and any destructor marked as @safe *must* be > > > idempotent. > > > > True. So any dtor that closes a file should set its handle to a > > null value so that any subsequent calls will be a no-op. [...] > The way I've learned to see it for decades now, initially from the > point of view of C++, calling the destructor more than once should be > a mistake. > > The reason is, when the destructor completes, the object is considered > to be dead. Calling any non-static function on it should be considered > a programming error.
I agree with this, in principle. Now, idempotent operations can also be helpful in some situations. It lets you elide verbose checks (like pervasive null checks peppering the code) by letting the caller ignore the exact state of an object because it's harmless (and does not change the result) to perform the operation twice. Idempotent destruction is questionable, however. If a dtor is called twice, then something smells bad, even if it's technically not wrong. It's the same as if a ctor were called twice to construct an object. The whole point of a ctor is to start from an invalid initial state and initialize the object into a valid state. Once that has been done, the object is already in a valid state and should not be initialized again -- the ctor code was written with the assumption that it wasn't in a valid state to start with. Violating this breaks the assumption, and this can lead to nasty bugs. Similarly, a dtor is written under the assumption that the object is in a valid state. After a dtor is finished the object is in an *invalid* state; calling it again breaks this assumption, which means it's liable to lead to nasty bugs. If druntime causes a ctor to run twice under any circumstances, I'd consider it a bug. Similarly, if a dtor were to run twice on the same object, I'd consider that a bug. T -- Roman numerals are difficult; but when you get to 159, it just CLIX.
