Currently calling .destroy(class_object) fails the @nogc tests. This is because the dynamic type of the object is not statically known and there's no restriction on child class destructors, so it has to assume the worst.
But what if the compiler simply inserted the call to super.dtor and all struct_member.dtors at the end of your destructor and did the attribute checks on them?
This would give you a chance to declare your more strict attributes while keeping everything in place - and any child class would no longer be able to loosen what's there. Meaning destroy(class_object) when the static type passed to destroy has a @nogc ~this, it'd be ok to propagate that up since it knows it all works, regardless of what chains get added.
If there is no dtor in a parent, there is no super call in the child, meaning it is also unrestricted and you can declare whatever you want.
if the dtor is all auto-generated and there is a super dtor, it inherits the attributes from super. If it is auto-generated and there is no super (meaning it just calls struct member dtors), it gets no attributes. Just because there's a @nogc struct member doesn't mean you should be locked in for child classes; I want it explicit if you want to opt into restrictions.