12.5.1 Formal Private and Derived Types
In its most general form, the category determined
for a formal private type is all types, but the category can be restricted
to only nonlimited types or to only tagged types. Similarly, the category
for a formal incomplete type is all types but the category can be restricted
to only tagged types; unlike other formal types, the actual type can
be incompletely defined, and not ready to be frozen (see
13.14).
The category determined for a formal derived type is the derivation class
rooted at the ancestor type.
Syntax
formal_private_type_definition ::= [[
abstract]
tagged] [
limited]
private
Legality Rules
The
ancestor
subtype of a formal derived type is the subtype denoted by the
subtype_mark
of the
formal_derived_type_definition.
For a formal derived type declaration, the reserved words
with private
shall appear if and only if the ancestor type is a tagged type; in this
case the formal derived type is a private extension of the ancestor type
and the ancestor shall not be a class-wide type. Similarly, an
interface_list
or the optional reserved words
abstract or
synchronized
shall appear only if the ancestor type is a tagged type. The reserved
word
limited or
synchronized shall appear only if the ancestor
type and any progenitor types are limited types. The reserved word
synchronized
shall appear (rather than
limited) if the ancestor type or any
of the progenitor types are synchronized interfaces. The ancestor type
shall be a limited interface if the reserved word
synchronized
appears.
The actual type for a formal derived type shall
be a descendant of the ancestor type and every progenitor of the formal
type. The actual type for a formal derived type shall be tagged if and
only if the formal derived type is a private extension. If the reserved
word synchronized appears in the declaration of the formal derived
type, the actual type shall be a synchronized tagged type.
If a formal private or derived subtype is definite,
then the actual subtype shall also be definite. If the formal type is
nonlimited, the actual type shall be nonlimited.
A
formal_incomplete_type_declaration
declares a formal incomplete type. The only view of a formal incomplete
type is an incomplete view. Thus, a formal incomplete type is subject
to the same usage restrictions as any other incomplete type — see
3.10.1.
For a generic formal
derived type with no
discriminant_part,
the actual subtype shall be statically compatible with the ancestor subtype.
Furthermore:
If the ancestor subtype is constrained, the actual
subtype shall be constrained;
If the ancestor subtype is an unconstrained access
or composite subtype, the actual subtype shall be unconstrained.
If the ancestor subtype is an unconstrained discriminated
subtype, then the actual shall have the same number of discriminants,
and each discriminant of the actual shall correspond to a discriminant
of the ancestor, in the sense of
3.7.
If the ancestor subtype is an access subtype, the
actual subtype shall exclude null if and only if the ancestor subtype
excludes null.
The actual type shall be a type with the same number
of discriminants.
The actual subtype shall be unconstrained.
The subtype of each discriminant of the actual
type shall statically match the subtype of the corresponding discriminant
of the formal type.
For a generic formal type with an
unknown_discriminant_part,
the actual may have discriminants, though that is not required, and may
be definite or indefinite.
When enforcing Legality Rules, for the purposes
of determining within a generic body whether a type is unconstrained
in any partial view, a discriminated subtype is considered to have a
constrained partial view if it is a descendant of an untagged generic
formal private or derived type.
Static Semantics
The category determined
for a formal private type is as follows:
Type Definition Determined Category
limited private the category of all types
private the category of all nonlimited types
tagged limited private the category of all tagged types
tagged private the category of all nonlimited tagged types
The presence of the reserved word abstract
determines whether the actual type may be abstract.
The category determined for a formal incomplete
type is the category of all types, unless the
formal_type_declaration
includes the reserved word
tagged; in this case, it is the category
of all tagged types.
A formal private or derived type is a private or
derived type, respectively. A formal derived tagged type is a private
extension. A formal private or derived type is abstract if the reserved
word abstract appears in its declaration.
For a formal derived type, the characteristics (including
components, but excluding discriminants if there is a new
discriminant_part),
predefined operators, and inherited user-defined primitive subprograms
are determined by its ancestor type and its progenitor types (if any),
in the same way that those of a derived type are determined by those
of its parent type and its progenitor types (see
3.4
and
7.3.1).
In an instance, the copy of an implicit declaration
of a primitive subprogram of a formal derived type declares a view of
the corresponding primitive subprogram of the ancestor or progenitor
of the formal derived type, even if this primitive has been overridden
for the actual type and even if it is never declared for the actual type.
When the ancestor or progenitor of the formal derived type is itself
a formal type, the copy of the implicit declaration declares a view of
the corresponding copied operation of the ancestor or progenitor. In
the case of a formal private extension, however, the tag of the formal
type is that of the actual type, so if the tag in a call is statically
determined to be that of the formal type, the body executed will be that
corresponding to the actual type.
In an instance, the implicitly composed and additive
aspects (see
13.1.1) of a formal type are
those of the actual; for a nonoverridable aspect, a formal derived type
inherits the aspect if the ancestor or any progenitor has the aspect,
according to the rules given in
13.1.
For a
prefix
S that denotes a formal indefinite subtype, the following attribute is
defined:
S'Definite
S'Definite yields True if the
actual subtype corresponding to S is definite; otherwise, it yields False.
The value of this attribute is of the predefined type Boolean.
Dynamic Semantics
In the case where
a formal type has unknown discriminants, and the actual type is a class-wide
type T'Class:
For the purposes of defining the primitive operations
of the formal type, each of the primitive operations of the actual type
is considered to be a subprogram (with an intrinsic calling convention
— see
6.3.1) whose body consists of
a dispatching call upon the corresponding operation of
T, with
its formal parameters as the actual parameters. If it is a function,
the result of the dispatching call is returned.
If the corresponding operation of
T has
no controlling formal parameters, then the controlling tag value is determined
by the context of the call, according to the rules for tag-indeterminate
calls (see
3.9.2 and
5.2).
In the case where the tag would be statically determined to be that of
the formal type, the call raises Program_Error. If such a function is
renamed, any call on the renaming raises Program_Error.
NOTE 1 The actual type can be abstract
only if the formal type is abstract (see
3.9.3).
NOTE 2 If the formal has a
discriminant_part,
the actual can be either definite or indefinite. Otherwise, the actual
can only be definite.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe