13.1.1 Aspect Specifications
{
AI05-0183-1}
[Certain representation or operational aspects of an entity may be specified
as part of its declaration using an
aspect_specification,
rather than using a separate representation or operational item.] The
declaration with the
aspect_specification
is termed the
associated declaration.
Syntax
Language Design Principles
{
AI05-0183-1}
{
AI05-0267-1}
The
aspect_specification
is an optional element in most kinds of declarations. Here is a list
of all kinds of declarations and an indication of whether or not they
allow aspect clauses, and in some cases a short discussion of why (*
= allowed, NO = not allowed). Kinds of declarations with no indication
are followed by their subdivisions (which have indications).
{
AI05-0267-1}
Syntactically,
aspect_specifications
generally are located at the end of declarations. When a declaration
is all in one piece such as a
null_procedure_declaration,
object_declaration,
or
generic_instantiation
the
aspect_specification
goes at the end of the declaration; it is then more visible and less
likely to interfere with the layout of the rest of the structure. However,
we make an exception for program units (other than subprogram specifications)
and bodies, in which the
aspect_specification
goes before the
is. In these cases, the entity could be large
and could contain other declarations that also have
aspect_specifications,
so it is better to put the
aspect_specification
toward the top of the declaration. (Some aspects – such as Pure
– also affect the legality of the contents of a unit, so it would
be annoying to only see those after reading the entire unit.)
Name Resolution Rules
{
AI05-0183-1}
{
AI12-0212-1}
An
aspect_mark
identifies an aspect of the entity defined by the associated declaration
(the
associated entity); the aspect denotes
an object, a value, an expression, an
aggregate,
a subprogram, or some other kind of entity. If the
aspect_mark
identifies:
an aspect that denotes an object, the
aspect_definition
shall be a
name.
The expected type for the
name
is the type of the identified aspect of the associated entity;
an aspect that is a value or an expression, the
aspect_definition
shall be an
expression.
The expected type for the
expression
is the type of the identified aspect of the associated entity;
Ramification: {
AI12-0212-1}
The only requirement here is that the
expression
is syntactically an
aggregate;
there is no requirement that it resolve to some particular type or even
that it should resolve like an
aggregate.
Each aspect that uses an
aggregate
is responsible for specifying how the choice(s), component(s), and other
contents of the
aggregate
are resolved and interpreted.
an aspect that denotes a subprogram, the
aspect_definition
shall be a
name;
the expected profile for the
name
is the profile required for the aspect of the associated entity;
an aspect that denotes some other kind of entity,
the
aspect_definition
shall be a
name,
and the name shall resolve to denote an entity of the appropriate kind;
an aspect that is given by an identifier specific
to the aspect, the
aspect_definition
shall be an
identifier,
and the
identifier
shall be one of the identifiers specific to the identified aspect.
{
AI05-0183-1}
{
AI12-0373-1}
{
AI12-0427-1}
The usage names in an
aspect_definition
associated with a declaration [ are not resolved at the point of the
associated declaration, but rather] are resolved at the end of the immediately
enclosing declaration list, or in the case of the declaration of a library
unit, at the end of the visible part of the entity.
{
AI05-0183-1}
{
AI12-0180-1}
{
AI12-0220-1}
If the associated declaration is for a subprogram, entry, or access-to-subprogram
type, the names of the formal parameters are directly visible within
the
aspect_definition,
as are certain attributes, as specified elsewhere in this document for
the identified aspect. If the associated declaration is a
type_declaration,
within the
aspect_definition
the names of any visible components, protected subprograms, and entries
are directly visible, and the name of the first subtype denotes the current
instance of the type (see
8.6). If the associated
declaration is a
subtype_declaration,
within the
aspect_definition
the name of the new subtype denotes the current instance of the subtype.
Legality Rules
{
AI05-0183-1}
If the first freezing point of the associated entity comes before the
end of the immediately enclosing declaration list, then each usage name
in the
aspect_definition
shall resolve to the same entity at the first freezing point as it does
at the end of the immediately enclosing declaration list.
Reason: {
AI12-0181-1}
{
AI12-0396-1}
The rule prevents an aspect of an entity from depending (directly or
indirectly) on properties of the entity itself.
Implementation Note: {
AI12-0396-1}
This check needs to be deferred at least to the freezing of the entity
(as the
aspect_definition
is not resolved until then), and might be accomplished during the freezing
of the
aspect_definition
(since it is closely related). Keep in mind that multiple other entities
could be involved.
{
AI05-0183-1}
At most one occurrence of each
aspect_mark
is allowed within a single
aspect_specification.
The aspect identified by the
aspect_mark
shall be an aspect that can be specified for the associated entity (or
view of the entity defined by the associated declaration).
{
AI05-0183-1}
If the
aspect_mark
includes 'Class, then the associated entity shall be a tagged type or
a primitive subprogram of a tagged type.
Discussion: {
AI12-0064-2}
Implementation-defined aspects can be allowed on these, of course; the
implementation will need to define the semantics. In addition, the language
does not define default aspect matching rules for generic formals; only
the handful of aspects allowed on formals have such rules. Therefore,
the implementation will need to define actual type matching rules for
any aspects allowed on formal types.
Reason: Most language-defined aspects
(for example, preconditions) are intended to be available to callers,
and specifying them on a body that has a separate declaration hides them
from callers. Specific language-defined aspects may allow this, but they
have to do so explicitly (by defining an alternative Legality Rule),
and provide any needed rules about visibility. Note that this rule does
not apply to implementation-defined aspects, so implementers need to
carefully define whether such aspects can be applied to bodies and stubs,
and what happens if they are specified on both the declaration and body
of a unit.
{
AI05-0183-1}
{
AI12-0138-1}
If an aspect of a derived type is inherited from an ancestor type and
has the boolean value True, the inherited value shall not be overridden
to have the value False for the derived type, unless otherwise specified
in this document.
Reason: Most boolean-valued language-defined
aspects are associated with a representation pragma. The existing rules
for such pragmas assume that the aspect cannot be removed. For instance,
if a type T is declared to be Atomic, then all descendants of
T are also Atomic. This rule ensures that remains the case when
using the aspect notation instead of pragmas.
Discussion: This definition leaves holes
for Boolean aspects that can be specified on non-first subtypes. Such
aspects (for instance, Nonblocking) must have their own rules (that is,
"otherwise specify" rules) that define the effects of inheriting
from subtypes (both first subtypes and nonfirst subtypes).
{
AI12-0396-1}
If a given aspect is type-related and inherited, then within an
aspect_definition
for the aspect, if a
name
resolves to denote multiple visible subprograms, all or none of the denoted
subprograms shall be primitives of the associated type.
Reason: {
AI12-0396-1}
This is necessary because the inheritance rules for
names
denoting primitive subprograms are different from those for
names
denoting other entities — see
13.1.
{
AI12-0138-1}
{
AI12-0206-1}
{
AI12-0419-1}
Certain type-related aspects are defined to be
nonoverridable;
all such aspects
are inherited by derived types according
to the rules given in
13.1. Any legality rule
associated with a nonoverridable aspect is re-checked for the derived
type, if the derived type is not abstract. Certain type-related and subtype-specific
aspects are defined to be
additive;
such aspects
are not inherited, but they can
apply to the
types derived from, or the subtypes based on, the original type or subtype,
as defined for each such aspect. Finally, certain type-related aspects
are
implicitly composed;
such aspects
are
not inherited, but rather a default implementation for a derived type
is provided, as defined for each such aspect, based on that of its parent
type, presuming the aspect for the parent type is available where the
derived type is declared, plus those of any new components added as part
of a type extension.
{
AI22-0002-1}
For a nonoverridable aspect of a type T
that denotes one or more subprograms with a parameter or result of type
T or access T, all of the denoted subprograms shall
be primitive for T. The same restriction applies to elements that
denote subprograms within a nonoverriddable aspect that is in the form
of an aggregate.
Reason: {
AI22-0002-1}
Nonoverridable aspects can only be confirmed on
inheritance, and a name that denotes a nonprimitive subprogram continues
to denote the original subprogram, thus there would be an inherited reference
to a subprogram that operates on the parent type rather than the derived
type. An example of an aspect that has elements that denote subprograms
is the Aggregate aspect.
{
AI12-0138-1}
{
AI12-0206-1}
{
AI12-0211-1}
{
AI12-0396-1}
{
AI22-0002-1}
If a nonoverridable aspect is directly specified for a type
T,
then any explicit specification of that aspect for any descendant of
T (other than
T itself) shall be
confirming.
In the case of an aspect that is a
name,
this means that the specified
name
shall
match the inherited aspect in the sense
that it shall denote the same declarations as would the inherited
name.
Similarly, for an aspect that is an
expression
or an
aggregate,
confirming means the defining
expression
is fully conformant (see
6.3.1) with the
defining
expression
for the inherited aspect, with the added rule that an identifier that
is specific to the aspect is the same as the corresponding identifier
in the inherited aspect.
{
AI12-0138-1}
{
AI12-0396-1}
{
AI22-0002-1}
If a full type has a partial view, and a given nonoverridable aspect
is allowed for both the full view and the partial view, then the given
aspect for the partial view and the full view shall be the same: the
aspect shall be directly specified only on the partial view; if the full
type inherits the aspect, then a matching definition shall be specified
(directly or by inheritance) for the partial view.
Ramification: In order to enforce these
rules without breaking privacy, we cannot allow a private type that could
have a particular overridable aspect to have a hidden definition of that
aspect. There is no problem if the private type does not allow the aspect
(as the aspect could not be specified on descendants in that case).
{
AI12-0211-1}
{
AI22-0002-1}
If a type inherits a nonoverridable aspect from multiple ancestors, the
value of the aspect inherited from any given ancestor shall be confirming
of the values inherited from all other ancestors.
Reason: {
AI12-0005-1}
{
AI12-0211-1}
If more than one progenitor of a type
T specifies a nonoverridable
aspect, they all have to specify the same or matching values for that
aspect. Otherwise, we'd have two different values for the aspect that
depend on which progenitor we inherit from.
{
AI12-0138-1}
{
AI12-0211-1}
{
AI22-0002-1}
In addition to the places where Legality Rules normally
apply (see
12.3), these rules about nonoverridable
aspects also apply in the private part of an instance of a generic unit.
Discussion: We don't need an assume-the-worst
rule for most nonoverridable aspects as they only work on tagged types
and deriving from formal tagged types is not allowed in generic bodies.
In the case of Implicit_Dereference, a derivation in a generic body does
not cause problems (the ancestor necessarily cannot have the aspect,
else specifying the aspect would be illegal), as there could be no place
with visibility on both aspects. In the case of Max_Entry_Queue_Length,
it is only allowed on task and protected types, and on entries, and there
are not formal versions of any of those things. In the case of No_Controlled_Parts,
we defined an assume-the-worst rule with the aspect.
{
AI12-0437-1}
A list of all nonoverridable aspects can be found in the index, under
“nonoverridable aspect”.
Static Semantics
a
name
that denotes a subprogram, object, or other kind of entity;
{
AI12-0427-1}
an
expression
(other than an
aggregate),
which is either evaluated to produce a single value, or which (as in
a precondition) is to be evaluated at particular points during later
execution;
{
AI12-0427-1}
an
aggregate,
which is positional or named, and is composed of elements of any of these
four kinds of constructs.
{
AI05-0183-1}
The identified aspect of the associated entity, or in some cases, the
view of the entity defined by the declaration, is as specified by the
aspect_definition
(or by the default of True when boolean). Whether an
aspect_specification
applies to an entity or only to the particular view of the entity
defined by the declaration is determined by the
aspect_mark
and the kind of entity. The following aspects are view specific:
{
AI05-0183-1}
All other
aspect_specifications
are associated with the entity, and
apply to all views of the
entity, unless otherwise specified in this document.
if the associated entity is a tagged type, the
specification
applies to all descendants of the type;
if the associated entity is a primitive subprogram
of a tagged type
T, the specification
applies to the corresponding
primitive subprogram of all descendants of
T.
{
AI12-0005-1}
Unless specified otherwise, all of the requirements for specifying a
particular aspect with an
attribute_definition_clause
also apply to an
aspect_specification
for the aspect. These are enforced at the freezing point of the entity.
For example, when specifying the Size aspect of a subtype, the expression
has to be a static expression with an integer type and a nonnegative
value, all of the recommended level of support requirements apply if
Annex C is supported (see
C.2),
and so on.
{
AI05-0229-1}
{
AI12-0154-1}
{
AI12-0417-1}
Some aspects are defined to be
library unit aspects.
Library unit aspects are of type Boolean. The expression specifying a
library unit aspect shall be static. Library unit aspects are defined
for all program units, but shall be specified only for library units.
Notwithstanding what this document says elsewhere, the expression of
a library unit aspect is resolved and evaluated at the point where it
occurs in the
aspect_specification[,
rather than the first freezing point of the associated unit].
Ramification: The name of the aspect
is the same as that of the pragma (see
13.1),
so the
aspect_mark
is the name of the pragma.
{
AI05-0229-1}
In addition, other operational and representation aspects not associated
with specifiable attributes or representation pragmas may be specified,
as specified elsewhere in this document.
Reason: Some rules only apply when an
aspect has been specified (for instance, an indexable type is one that
has aspect Variable_Indexing specified). In order to prevent privacy
breaking, this can only be true when the specification of the aspect
is visible. In particular, if the Variable_Indexing aspect is specified
on the full view of a private type, the private type is not considered
an indexable type.
{
AI05-0183-1}
Alternative legality and semantics rules may apply for particular aspects,
as specified elsewhere in this document.
Dynamic Semantics
{
AI05-0183-1}
{
AI12-0355-2}
At the freezing point of the associated entity, the
aspect_specification
is elaborated. When appearing in a construct other than a declaration,
an
aspect_specification
is elaborated as part of the execution of the construct. The elaboration
of the
aspect_specification
consists of the elaboration of each
aspect_definition
in an arbitrary order. The elaboration of an
aspect_definition
includes the evaluation of any
name
or
expression
that is part of the
aspect_definition
unless the part is itself an expression. If the corresponding aspect
(or part thereof) represents an expression (as in a precondition), the
elaboration of that part has no effect; the expression is evaluated later
at points within the execution as specified elsewhere in this document
for the particular aspect.
Implementation Permissions
{
AI05-0183-1}
Implementations may support implementation-defined aspects. The
aspect_specification
for an implementation-defined aspect may use an implementation-defined
syntax for the
aspect_definition,
and may follow implementation-defined legality and semantics rules.
Implementation defined: Implementation-defined
aspects, including the syntax for specifying such aspects and the legality
rules for such aspects.
{
AI12-0389-1}
An implementation may ignore the specification of an unrecognized aspect;
if an implementation chooses to ignore such an aspect specification (as
opposed to rejecting it), then it has no effect on the semantics of the
program except for possibly (and this is not required) the rejection
of syntax errors within the
aspect_definition.
Discussion: {
AI12-0389-1}
Identifying the textual end of an
aspect_definition
for an unrecognized aspect may be challenging, particularly if the syntax
for the unrecognized aspect's
aspect_definition
is implementation-defined. It is not specified how an implementation
might accomplish this. Note that an implementation is never
required
to be able to do this; if an
aspect_definition
for an unrecognized aspect is problematic in any way, then it can always
be rejected (as opposed to being ignored).
Extensions to Ada 2005
Inconsistencies With Ada 2012
{
AI12-0180-1}
Correction: Names of protected subprograms
and entries are now directly visible in an aspect of a type declaration.
This was always intended to be the case, but it was omitted from the
Reference Manual by an editing error. In the unlikely case that a parameterless
protected function has the same name and type as an entity used in a
type invariant expression, the meaning would change from the outside
entity which would now be hidden by the protected function. It is much
more likely that a conflict (itself rather unlikely) would cause a resolution
failure.
Incompatibilities With Ada 2012
{
AI12-0154-1}
Corrigendum: Added a clarification that aspects
that correspond to library unit pragmas are resolved and evaluated immediately.
This is incompatible, as a reference to an entity defined after the aspect
will now be illegal. However, this would have required retroactive enforcement
of such aspects, which is a new capability not available from the associated
pragma, and moreover no known Ada 2012 implementation has ever allowed
late evaluation of such aspects. As such, there should be no practical
incompatibility.
{
AI12-0005-1}
{
AI12-0220-1}
Parameters of access-to-subprogram types are now visible in aspect specifications.
This can be incompatible if some entity with the same name as a parameter
is used in an existing aspect specification. We believe that all such
aspects require either static expressions or a subprogram that is statically
denoted; since a parameter can be neither of these and hides everything
else, all such cases will be caught at compile-time. In addition, we
expect such cases to be very rare.
Extensions to Ada 2012
{
AI12-0212-1}
An aspect can be an unresolved
aggregate,
these can be used to specify a list of entities, or to set a group of
different but related properties with a single aspect.
{
AI12-0355-2}
Aspect specifications can appear in, and apply to, constructs other than
declarations.
{
AI12-0389-1}
An unrecognized aspect specification can be ignored.
Wording Changes from Ada 2012
{
AI12-0105-1}
Corrigendum: Clarified the wording so that the restriction against
language-defined aspects on subprogram completions includes completions
that are expressions functions and null procedures.
{
AI12-0138-1}
Corrigendum: Added a definition of nonoverridable aspects. This
is necessary to prevent generic contract problems with formal derived
types.
{
AI12-0206-1}
Correction: Extended the definition of nonoverridable aspects
to cover most kinds of aspects.
{
AI12-0211-1}
Correction: Added a rule so that the a nonoverridable aspect has
to be the same for every ancestor of a type.
{
AI12-0380-1}
{
AI12-0407-1}
Revised the rules about entities that cannot have specified language-defined
aspects. The body portion of the rule was changed to a general prohibition
on specifying language-defined aspects on completions (this allows specifying
aspects on bodies that act as a declaration, and eliminates the list
of entities, which was a maintenance nightmare). Then the remaining entities
(renamings and generic formal parameters) were revised to allow specific
aspects, since Nonblocking (see
9.5), as well
as Pre and Post, are now allowed on generic formal parameters.
{
AI12-0373-1}
Added the missing definition for resolution of entities found in aspects
of library units.
{
AI12-0419-1}
Added a description of additive and implicitly composed aspects in order
to explain the different inheritance mechanisms used by existing aspects.
Incompatibilities With Ada 2022
{
AI22-0002-1}
Corrigendum: If a nonoverridable
aspect is specified by a subprogram that is not primitive, and the associated
type is never derived, the program was legal in Ada 2022 but now is illegal.
(If the type was derived, it was unclear what would happen; the subprogram
would have parameters and/or results of the wrong type.)
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe