12.5 Formal Types
This Reference Manual output has not been verified, and may contain omissions or errors. Report any problems on the tracking issue
[A generic formal subtype can be used to pass to a generic unit a subtype whose type is in a certain category of types.]
formal_integer_type_definition
, formal_real_type_definition
, and formal_fixed_point_definition
, to be more uniform with the syntax rules for non-generic-formal types. However, that would make the rules for formal types slightly more complicated, and it would cause confusion, since formal_discrete_type_definition
would not fit into the scheme very well. Syntax
2/3formal_type_declaration
::=
formal_complete_type_declaration
| formal_incomplete_type_declaration
2.1/5formal_complete_type_declaration
::=
type defining_identifier
[discriminant_part
] is formal_type_definition
[or use default_subtype_mark
] [aspect_specification
];
2.2/5formal_incomplete_type_declaration
::=
type defining_identifier
[discriminant_part
] [is tagged]
[or use default_subtype_mark
];
3/2formal_type_definition
::=
formal_private_type_definition
| formal_derived_type_definition
| formal_discrete_type_definition
| formal_signed_integer_type_definition
| formal_modular_type_definition
| formal_floating_point_definition
| formal_ordinary_fixed_point_definition
| formal_decimal_fixed_point_definition
| formal_array_type_definition
| formal_access_type_definition
| formal_interface_type_definition
Legality Rules
4For a generic formal subtype, the actual shall be a subtype_mark
; it denotes the (generic) actual subtype.
formal_type_declaration
denotes a subtype, and the corresponding actual also denotes a subtype. Static Semantics
5A formal_type_declaration
declares a (generic) formal type, and its first subtype, the (generic) formal subtype.
The form of a formal_type_definition
determines a category (of types) to which the formal type belongs. For a formal_private_type_definition
the reserved words tagged and limited indicate the category of types (see 12.5.1). The reserved word tagged also plays this role in the case of a formal_incomplete_type_declaration
. For a formal_derived_type_definition
the category of types is the derivation class rooted at the ancestor type. For other formal types, the name of the syntactic category indicates the category of types; a formal_discrete_type_definition
defines a discrete type, and so on.
formal_type_definition
given above. Adding formal_integer_type_definition
and others would make this rule harder to state clearly.Legality Rules
7/2The actual type shall be in the category determined for the formal.
The default_subtype_mark
, if any, shall denote a subtype which is allowed as an actual subtype for the formal type.
generic_declaration
, and is consistent with the handling of the default_name
of a formal subprogram. This means that a type declared outside of the generic_declaration
cannot be used as the default_subtype_mark
for a formal type that depends on any other formal type. Static Semantics
8/5{8652/0037} [The formal type also belongs to each category that contains the determined category.] The primitive subprograms of the type are as for any type in the determined category. For a formal type other than a formal derived type, these are the predefined operators of the type. For an elementary formal type, the predefined operators are implicitly declared immediately after the declaration of the formal type. For a composite formal type, the predefined operators are implicitly declared either immediately after the declaration of the formal type, or later immediately within the declarative region in which the type is declared according to the rules of 7.3.1. In an instance, the copy of such an implicit declaration declares a view of the predefined operator of the actual type, even if this operator has been overridden for the actual type and even if it is never declared for the actual type, unless the actual type is an untagged record type, in which case it declares a view of the primitive (equality) operator. [The rules specific to formal derived types are given in 12.5.1.]
constraint
applicable to a formal type in a subtype_indication
depends on the category of the type as for a nonformal type. The formal type is tagged if and only if it is declared as a tagged private type, or as a type derived from a (visibly) tagged type. (Note that the actual type might be tagged even if the formal type is not.)package Q is
type T is limited private;
private
type T is range 1 .. 10;
end Q;
8.d/3generic
type A is array (Positive range <>) of T;
package Q.G is
A1, A2 : A (1 .. 1);
private
B : Boolean := A1 = A2;
end Q.G;
8.e/3with Q.G;
package R is
type C is array (Positive range <>) of Q.T;
8.f/3package I is new Q.G (C); -- Where is the predefined "=" for C?
end R;
name
can denote a generic formal subtype. Within a generic unit, a generic formal type is considered as being distinct from all other (formal or nonformal) types. formal_type_declaration
declares a type. discriminant_part
is allowed only for certain kinds of types, and therefore only for certain kinds of generic formal types. See 3.7. formal_floating_point_definition
. It does not include a formal derived type whose ancestor is a floating point type. Similar terminology applies to the other kinds of formal_type_definition
. Examples
11Examples of generic formal types:
type Item is private;
type Buffer(Length : Natural) is limited private;
13type Enum is (<>);
type Int is range <>;
type Angle is delta <>;
type Mass is digits <>;
14type Table is array (Enum) of Item;
15Example of a generic formal part declaring a formal integer type:
generic
type Rank is range <>;
First : Rank := Rank'First;
Second : Rank := First + 1; -- the operator "+" of the type Rank
Wording Changes from Ada 83
Wording Changes from Ada 95
Extensions to Ada 2005
aspect_specification
can be used in a formal_type_declaration
. This is described in 13.1.1. Wording Changes from Ada 2005
Inconsistencies With Ada 2012
Extensions to Ada 2012
12.5.1 Formal Private and Derived Types
1/5[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
2formal_private_type_definition
::=
[[abstract] tagged] [limited] private
3/2formal_derived_type_definition
::=
[abstract] [limited | synchronized] new subtype_mark
[[and interface_list
]with private]
Legality Rules
4If a generic formal type declaration has a known_discriminant_part
, then it shall not include a default_expression
for a discriminant.
known_discriminant_part
is an indefinite subtype, so the declaration of a stand-alone variable has to provide a constraint on such a subtype, either explicitly, or by its initial value. 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.
unknown_discriminant_part
may be used to relax these matching requirements. - If the ancestor subtype is an access subtype, the actual subtype shall exclude null if and only if the ancestor subtype excludes null.
The declaration of a formal derived type shall not have a known_discriminant_part
. For a generic formal private or incomplete type with a known_discriminant_part
:
- 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.
discriminant_part
s. We rejected that idea, because it would require implicit (inherited) discriminant_part
s, which seemed like too much mechanism. [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
16/2The 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).
{8652/0038} 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.]
default_expression
s are determined by those of the primitive subprograms of the specified ancestor type (or progenitor type, for subprograms inherited from an interface 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
23.1/3In 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.
generic
type NT(<>) is new T with private;
-- Assume T has operation "function Empty return T;"
package G is
procedure Test(X : in out NT);
end G;
23.e/2package body G is
procedure Test(X : in out NT) is
begin
X := Empty; -- Dispatching based on X'Tag takes
-- place if actual is class-wide.
declare
Y : NT := Empty;
-- If actual is class-wide, this raises Program_Error
-- as there is no tag provided by context.
begin
X := Y; -- We never get this far.
end;
end Test;
end G;
23.f/2type T1 is new T with null record;
package I is new G(T1'Class);
discriminant_part
, the actual can be either definite or indefinite. Otherwise, the actual has to be definite. Incompatibilities With Ada 83
unknown_discriminant_part
s, so it allows indefinite subtypes to be passed to definite formals, and applies a legality rule to the instance body. This is a contract model violation. Ada 95 disallows such cases at the point of the instantiation. The workaround is to add (<>) as the discriminant_part
of any formal subtype if it is intended to be used with indefinite actuals. If that's the intent, then there can't be anything in the generic body that would require a definite subtype.Extensions to Ada 95
Wording Changes from Ada 95
Incompatibilities With Ada 2005
Extensions to Ada 2005
Wording Changes from Ada 2005
Incompatibilities With Ada 2012
Wording Changes from Ada 2012
12.5.2 Formal Scalar Types
1/2A formal scalar type is one defined by any of the formal_type_definition
s in this subclause. [The category determined for a formal scalar type is the category of all discrete, signed integer, modular, floating point, ordinary fixed point, or decimal types.]
Syntax
2formal_discrete_type_definition
::=
(<>)
3formal_signed_integer_type_definition
::=
range <>
4formal_modular_type_definition
::=
mod <>
5formal_floating_point_definition
::=
digits <>
6formal_ordinary_fixed_point_definition
::=
delta <>
7formal_decimal_fixed_point_definition
::=
delta <> digits <>
Legality Rules
8The actual type for a formal scalar type shall not be a nonstandard numeric type.
Wording Changes from Ada 95
12.5.3 Formal Array Types
1/2[The category determined for a formal array type is the category of all array types.]
Syntax
2formal_array_type_definition
::=
array_type_definition
Legality Rules
3The only form of discrete_subtype_definition
that is allowed within the declaration of a generic formal (constrained) array subtype is a subtype_mark
.
For a formal array subtype, the actual subtype shall satisfy the following conditions:
- The formal array type and the actual array type shall have the same dimensionality; the formal subtype and the actual subtype shall be either both constrained or both unconstrained.
- For each index position, the index types shall be the same, and the index subtypes (if unconstrained), or the index ranges (if constrained), shall statically match (see 4.9.1).
- The component subtypes of the formal and actual array types shall statically match.
- If the formal type has aliased components, then so shall the actual.
Examples
9Example of formal array types:
-- given the generic package
11generic
type Item is private;
type Index is (<>);
type Vector is array (Index range <>) of Item;
type Table is array (Index) of Item;
package P is
...
end P;
12-- and the types
13type Mix is array (Color range <>) of Boolean;
type Option is array (Color) of Boolean;
14-- then Mix can match Vector and Option can match Table
15package R is new P(Item => Boolean, Index => Color,
Vector => Mix, Table => Option);
16-- Note that Mix cannot match Table and Option cannot match Vector
Incompatibilities With Ada 83
Wording Changes from Ada 95
12.5.4 Formal Access Types
1/2[The category determined for a formal access type is the category of all access types.]
Syntax
2formal_access_type_definition
::=
access_type_definition
Legality Rules
3For a formal access-to-object type, the designated subtypes of the formal and actual types shall statically match.
If and only if the general_access_modifier
constant applies to the formal, the actual shall be an access-to-constant type. If the general_access_modifier
all applies to the formal, then the actual shall be a general access-to-variable type (see 3.10). If and only if the formal subtype excludes null, the actual subtype shall exclude null.
_modifier
applies to the formal, then the actual type may be either a pool-specific or a general access-to-variable type. For a formal access-to-subprogram subtype, the designated profiles of the formal and the actual shall be subtype conformant.
Examples
6Example of formal access types:
-- the formal types of the generic package
8generic
type Node is private;
type Link is access Node;
package P is
...
end P;
9-- can be matched by the actual types
10type Car;
type Car_Name is access Car;
11type Car is
record
Pred, Succ : Car_Name;
Number : License_Number;
Owner : Person;
end record;
12-- in the following generic instantiation
13package R is new P(Node => Car, Link => Car_Name);
Incompatibilities With Ada 83
Extensions to Ada 83
Wording Changes from Ada 95
Incompatibilities With Ada 2005
12.5.5 Formal Interface Types
1/2[The category determined for a formal interface type is the category of all interface types.]
Syntax
2/2formal_interface_type_definition
::=
interface_type_definition
Legality Rules
3/2The actual type shall be a descendant of every progenitor of the formal type.
The actual type shall be a limited, task, protected, or synchronized interface if and only if the formal type is also, respectively, a limited, task, protected, or synchronized interface.
Examples
5/5Example of the use of a generic with a formal interface type, to establish a standard interface that all tasks will implement so they can be managed appropriately by an application-specific scheduler:
type Root_Work_Item is tagged private;
7/2generic
type Managed_Task is task interface;
type Work_Item(<>) is new Root_Work_Item with private;
package Server_Manager is
task type Server is new Managed_Task with
entry Start(Data : in out Work_Item);
end Server;
end Server_Manager;
8/5