7.3.4 Stable Properties of a Type
{
AI12-0187-1}
{
AI12-0324-1}
Certain characteristics of an object of a given
type are unchanged by most of the primitive operations of the type. Such
characteristics are called stable properties of the type.
Term entry: stable
property — characteristic associated with objects of a given
type that is preserved by many of the primitive operations of the type
Static Semantics
{
AI12-0187-1}
A property function of type T is
a function with a single parameter of type T or of a class-wide
type that covers T.
Reason: This provides
restrictions on name resolution so overloaded functions can be used as
a stable property function.
This aspect shall be specified by a type property
aspect definition; each name
shall statically denote a single property function of the type. This
aspect defines the specific stable property functions of the associated
type.
Discussion: We
do not allow this aspect on generic formal types, as it is only meaningful
for primitive subprograms and generic formal types have no such subprograms.
Ramification: Class-wide
aspects are only allowed on tagged types (see 13.1.1),
so we don't say that here.
Aspect Description
for Stable_Properties: A
list of functions describing characteristics that usually are unchanged
by primitive operations of the type or an individual primitive subprogram.
This aspect shall be specified by a type property
aspect definition; each name
shall statically denote a single property function of the type. This
aspect defines the class-wide stable property functions of the
associated type. [Unlike most class-wide aspects, Stable_Properties'Class
is not inherited by descendant types and subprograms, but the enhanced
class-wide postconditions are inherited in the normal manner.]
Proof: Class-wide
inheritance has to be explicitly defined. Here we are not making such
a definition, so there is no inheritance. 6.1.1
defines the inheritance of class-wide postconditions.
Discussion: Since
class-wide postconditions are inherited by descendants, we don't need
the stable property functions to be inherited; if they were inherited,
we'd be duplicating the checks, which we don't want.
Ramification: Class-wide
aspects are only allowed on primitive subprograms of tagged types (see
13.1.1), so we don't say that here.
Aspect Description
for Stable_Properties'Class: A
list of functions describing characteristics that usually are unchanged
by primitive operations of a class of types or a primitive subprogram
for such a class.
{
AI12-0405-1}
The specific and class-wide stable properties of
a type together comprise the stable properties of the type.
This aspect shall be specified by a subprogram
property aspect definition; each name
shall statically denote a single property function of a type for which
the associated subprogram is primitive.
This aspect shall be specified by a subprogram
property aspect definition; each name
shall statically denote a single property function of a tagged type for
which the associated subprogram is primitive. [Unlike most class-wide
aspects, Stable_Properties'Class is not inherited by descendant subprograms,
but the enhanced class-wide postconditions are inherited in the normal
manner.]
Reason: The subprogram
versions of Stable_Properties are provided to allow overriding the stable
properties of a type for an individual primitive subprogram. While they
can be used even if the type has no stable properties, that is not an
intended use (as simply modifying the postcondition directly makes more
sense for something that only happens in one place).
Legality Rules
{
AI12-0187-1}
A stable property function of a type T shall
have a nonlimited return type and shall be:
a primitive function with
a single parameter of mode in of type T; or
a function that is declared
immediately within the declarative region in which an ancestor type of
T is declared and has a single parameter of mode in of
a class-wide type that covers T.
all or none of the items
shall be preceded by not;
Ramification: Mixing
not functions with regular functions is not allowed.
any property functions mentioned
after not shall be a stable property function of a type for which
S is primitive.
{
AI12-0405-1}
If a subprogram_renaming_declaration
declares a primitive subprogram of a type T, then the renamed
callable entity shall also be a primitive subprogram of type T
and the two primitive subprograms shall have the same specific stable
property functions and the same class-wide stable property functions
(see below).
Static Semantics
{
AI12-0187-1}
For a primitive subprogram S of a type T,
the specific stable property functions of S for type T
are:
if S has an aspect
Stable_Properties specified that does not include not, those functions
denoted in the aspect Stable_Properties for S that have a parameter
of T or T'Class;
if S has an aspect
Stable_Properties specified that includes not, those functions
denoted in the aspect Stable_Properties for T, excluding those
denoted in the aspect Stable_Properties for S;
if S does not have
an aspect Stable_Properties, those functions denoted in the aspect Stable_Properties
for T, if any.
Discussion: A primitive
subprogram can be primitive for more than one type, and thus there can
be more than one such set of specific stable properties for a subprogram.
Thus we say “specific stable property functions for subprogram
S for type T”.
{
AI12-0187-1}
A similar definition applies for class-wide stable
property functions by replacing aspect Stable_Properties with aspect
Stable_Properties'Class in the above definition.
{
AI12-0187-1}
The explicit specific postcondition expression
for a subprogram S is the expression
directly specified for S with the Post aspect. Similarly, the
explicit class-wide postcondition expression for a subprogram
S is the expression
directly specified for S with the Post'Class aspect.
{
AI12-0187-1}
For a primitive subprogram S of a type T
that has a parameter P of type T, the parameter is excluded
from stable property checks if:
S is a stable property
function of T;
Reason: This prevents
possible infinite recursion, where the postcondition calls the function
itself (directly or indirectly).
P has mode out;
Reason: A parameter
of mode out doesn't necessarily have a defined input value, so
there is no old value to compare with. Ideally, the postcondition will
include expressions defining the values of the stable properties after
the call, but we do not try to ensure this.
the Global aspect of S
is null, and P has mode in and the mode is not overridden
by a global aspect.
Reason: An in
parameter of a Global => null subprogram cannot be modified,
even if it has indirect parts, without violating the Global aspect. Thus,
there is no need to assert that the properties don't change.
{
AI12-0187-1}
{
AI12-0324-1}
{
AI12-0405-1}
For every primitive subprogram S of a type
T that is not an abstract subprogram or null procedure, the specific
postcondition expression of S is modified to include expressions
of the form F(P) = F(P)'Old, all
anded with each other and any explicit specific postcondition
expression, with one such equality included for each specific stable
property function F of S for type T that does not
occur in the explicit specific postcondition expression of S,
and P is each parameter of S that has type T and
is not excluded from stable property checks. The resulting specific postcondition
expression of S is used in place of the explicit specific postcondition
expression of S [when interpreting the meaning of the postcondition
as defined in 6.1.1].
Ramification: There
is one F(P) = F(P)'Old subexpression for every combination of
a specific stable property function of type T and a parameter
of type T. For instance, if there are three specific stable property
functions for type T and two parameters of type T, then
there are six such subexpressions appended to the postcondition.
The resulting specific
postcondition is evaluated as described in 6.1.1.
One hopes that compilers can be smart enough to prove that many of these
added postcondition subexpressions cannot fail, but that is not required
here.
Reason: Null procedures
and abstract subprograms are excluded as they do not allow specific postconditions.
Moreover, for null procedures, static analysis tools can be certain that
their parameters aren't modified so there is no need to assert that the
properties don't change. Abstract subprograms cannot be directly called.
{
AI12-0187-1}
{
AI12-0324-1}
{
AI12-0405-1}
For every primitive subprogram S of a type
T, the class-wide postcondition expression of S is modified
to include expressions of the form F(P) = F(P)'Old,
all anded with each other and any explicit class-wide postcondition
expression, with one such equality included for each class-wide stable
property function F of S for type T that does not
occur in any class-wide postcondition expression that applies to S,
and P is each parameter of S that has type T and
is not excluded from stable property checks. The resulting class-wide
postcondition expression of S is used in place of the explicit
class-wide postcondition expression of S [when interpreting the
meaning of the postcondition as defined in 6.1.1].
Reason: We suppress
stable property expressions if the property function appears in the explicit
class-wide postcondition, or in any inherited class-wide postconditions.
If we didn't do that, we could have conflicting requirements in an inherited
postcondition and the current one. We also avoid redundant property checks.
Ramification: The
resulting class-wide postcondition is evaluated as described in 6.1.1.
In particular, the enhanced class-wide postcondition is the class-wide
postcondition for S, and therefore inherited postconditions include
any stable property expressions for S.
{
AI12-0405-1}
In the case of a derived type T, when the
preceding rules refer to “every primitive subprogram S of
a type T”, the referenced set of subprograms includes any
inherited subprograms.
{
AI12-0405-1}
The Post expression additions described above are
enabled or disabled depending on the Post assertion policy that is in
effect at the point of declaration of the subprogram S. A similar
rule applies to the Post'Class expression additions.
NOTE {
AI12-0112-1}
For an example of the use of these aspects, see
the Vector container definition in A.18.2.
Extensions to Ada 2012
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe