17.3.13 Destructors

The Destructor aspect can be applied to any record type, tagged or not. It must denote a primitive of the type that is a procedure with one parameter of the type and of mode in out:

type T is record
   ...
end record with Destructor => Foo;

procedure Foo (X : in out T);

This is equivalent to the following code that uses Finalizable:

type T is record
   ...
end record with Finalizable => (Finalize => Foo);

procedure Foo (X : in out T);

Unlike Finalizable, however, Destructor can be specified on a derived type. And when it is, the effect of the aspect combines with the destructors of the parent type. Take, for example:

type T1 is record
   ...
end record with Destructor => Foo;

procedure Foo (X : in out T1);

type T2 is new T1 with Destructor => Bar;

procedure Bar (X : in out T2);

Here, when an object of type T2 is finalized, a call to Bar will be performed and it will be followed by a call to Foo.

The Destructor aspect comes with a legality rule: if a primitive procedure of a type is denoted by a Destructor aspect specification, it is illegal to override this procedure in a derived type. For example, the following is illegal:

type T1 is record
   ...
end record with Destructor => Foo;

procedure Foo (X : in out T1);

type T2 is new T1;

overriding
procedure Foo (X : in out T2); -- Error here

It is possible to specify Destructor on the completion of a private type, but there is one more restriction in that case: the denoted primitive must be private to the enclosing package. This is necessary due to the previously mentioned legality rule, to prevent breaking the privacy of the type when imposing that rule on outside types that derive from the private view of the type.