12.3 Generic Instantiation
Language Design Principles
The legality of an instance should
be determinable without looking at the generic body. Likewise, the legality
of a generic body should be determinable without looking at any instances.
Thus, the generic_declaration
forms a contract between the body and the instances; if each obeys the
rules with respect to the generic_declaration
then no legality problems will arise. This is really a special case of
the “legality determinable via semantic dependences” Language
Design Principle (see Clause 10
), given that
does not depend semantically upon the generic body, nor vice -
Run-time issues are another story. For example,
whether parameter passing is by copy or by reference is determined in
part by the properties of the generic actuals, and thus cannot be determined
at compile time of the generic body. Similarly, the contract model does
not apply to Post-Compilation Rules.
according to whether or not the
is specified. Any positional associations shall precede any named associations.
In a generic_instantiation
for a particular kind of program unit [(package, procedure, or function)],
denote a generic unit of the corresponding kind [(generic package, generic
procedure, or generic function, respectively)].
In a generic unit Legality Rules are enforced at
compile time of the generic_declaration
and generic body, given the properties of the formals. In the visible
part and formal part of an instance, Legality Rules are enforced at compile
time of the generic_instantiation
given the properties of the actuals. In other parts of an instance, Legality
Rules are not enforced; this rule does not apply when a given rule explicitly
Since rules are checked using the properties of the formals, and since
these properties do not always carry over to the actuals, we need to
check the rules again in the visible part of the instance. For example,
only if a tagged type is limited may an extension of it have limited
components in the record_extension_part
A formal tagged limited type is limited, but the actual might be nonlimited.
Hence any rule that requires a tagged type to be limited runs into this
problem. Such rules are rare; in most cases, the rules for matching of
formals and actuals guarantee that if the rule is obeyed in the generic
unit, then it has to be obeyed in the instance.
Ada 2012 addendum: Such Legality Rules are not as rare as the authors
of Ada 95 hoped; there are more than 30 of them known at this point.
They are indexed under "generic contract issue" and are associated
with the boilerplate "In addition to the places where Legality Rules
normally apply...". Indeed, there is only one known rule where rechecking
in the specification is needed and where rechecking in the private part
wanted (it is in 3.4
, but even
it needs rechecking when tagged types are involved).
The “properties” of the formals are determined without
knowing anything about the actuals:
A formal derived subtype is constrained if and only if the ancestor subtype
is constrained. A formal array type is constrained if and only if the
declarations say so. A formal private type is constrained if it does
not have a discriminant part. Other formal subtypes are unconstrained,
even though they might be constrained in an instance.
A formal subtype can be indefinite, even though
the copy might be definite in an instance.
A formal object of mode in is not a
static constant; in an instance, the copy is static if the actual is.
A formal subtype is not static, even though
the actual might be.
Formal types are specific, even though the
actual can be class-wide.
The subtype of a formal object of mode in
out is not static. (This covers the case of AI83-00878.)
The subtype of a formal parameter of a formal
subprogram does not provide an applicable index constraint.
The profile of a formal subprogram is not subtype conformant with any
A generic formal function is not static.
The exceptions to the above rule about when legality rules are enforced
fall into these categories:
Some rules are
checked in the generic declaration, and then again in both the visible
and private parts of the instance:
The parent type of a record
extension has to be specific (see 3.9.1
This rule is not checked in the instance body.
The parent type of a private
extension has to be specific (see 7.3
rule is not checked in the instance body.
A type with an access discriminant with a default_expression
has to be immutably limited. In the generic body, the definition of immutably
limited is adjusted in an assume-the-worst manner (thus the rule is checked
In the declaration of a record
extension, if the parent type is nonlimited, then each of the components
of the record_extension_part
have to be nonlimited (see 3.9.1
). In the
generic body, this rule is checked in an assume-the-worst manner.
A preelaborated library unit
has to be preelaborable (see 10.2.1
the generic body, this rule is checked in an assume-the-worst manner.
The corrections made by the Corrigendum added a number of such rules,
and the Amendment added many more. There doesn't seem to be much value
in repeating all of these rules here (as of this writing, there are roughly
33 such rules). As noted below, all such rules are indexed in the AARM.
For the accessibility
rules, the formals have nothing to say about the property in question.
Like the above rules, these rules are checked in the generic declaration,
and then again in both the visible and private parts of the instance.
In the generic body, we have explicit rules that essentially assume the
worst (in the cases of type extensions and access-to-subprogram types),
and we have runtime checks (in the case of access-to-object types). See
We considered runtime checks for
access-to-subprogram types as well. However, this would present difficulties
for implementations that share generic bodies.
The rules requiring “reasonable”
values for static expressions are ignored when the expected type for
the expression is a descendant of a generic formal type other than a
generic formal derived type, and do not apply in an instance.
The rule forbidding two explicit homographs
in the same declarative region does not apply in an instance of a generic
unit, except that it does apply in the declaration of a record
extension that appears in the visible part of an instance.
Some rules do
not apply at all in an instance, not even in the visible part:
are not normally allowed to be multiply nested, but they can be in instances.
Each rule that is an exception
is marked with “generic contract issue;” look that up in
the index to find them all.
Ramification: The Legality Rules are
the ones labeled Legality Rules. We are talking about all Legality Rules
in the entire language here. Note that, with some exceptions, the legality
of a generic unit is checked even if there are no instantiations of the
The Legality Rules are described here, and the overloading rules were
described earlier in this subclause. Presumably, every Static Semantic
Item is sucked in by one of those. Thus, we have covered all the compile-time
rules of the language. There is no need to say anything special about
the Post-Compilation Rules or the Dynamic Semantic Items.
Here is an example illustrating
how this rule is checked: “In the declaration of a record extension,
if the parent type is nonlimited, then each of the components of the
shall be nonlimited.”
type Parent is tagged private;
type Comp is limited private;
package G1 is
type Extension is new Parent with
C : Comp; -- Illegal!
The parent type is nonlimited, and the component
type is limited, which is illegal. It doesn't matter that one could imagine
writing an instantiation with the actual for Comp being nonlimited —
we never get to the instance, because the generic itself is illegal.
On the other hand:
type Parent is tagged limited private; -- Parent is limited.
type Comp is limited private;
package G2 is
type Extension is new Parent with
C : Comp; -- OK.
type Limited_Tagged is tagged limited null record;
type Non_Limited_Tagged is tagged null record;
type Limited_Untagged is limited null record;
type Non_Limited_Untagged is null record;
package Good_1 is new G2(Parent => Limited_Tagged,
Comp => Limited_Untagged);
package Good_2 is new G2(Parent => Non_Limited_Tagged,
Comp => Non_Limited_Untagged);
package Bad is new G2(Parent => Non_Limited_Tagged,
Comp => Limited_Untagged); -- Illegal!
The first instantiation is legal, because in
the instance the parent is limited, so the rule is not violated. Likewise,
in the second instantiation, the rule is not violated in the instance.
However, in the Bad instance, the parent type is nonlimited, and the
component type is limited, so this instantiation is illegal.
The declaration and the
body of the instance are not “implicit” in the technical
sense, even though you can't see them in the program text. Nor are declarations
within an instance “implicit” (unless they are implicit by
other rules). This is necessary because implicit declarations have special
semantics that should not be attached to instances. For a generic subprogram,
the profile of a generic_instantiation
is that of the instance declaration, by the stated equivalence.
The instance is a copy of the text of the template.
[Each use of a formal parameter becomes (in the copy) a use of the actual,
as explained below.]
instance of a generic package is a package, that of a generic procedure
is a procedure, and that of a generic function is a function.
An instance is a package
or subprogram (because we say so), even though it contains a copy of
and therefore doesn't look like one. This is strange, but it's OK, since
the syntax rules are overloading rules, and therefore do not apply in
We use a macro-expansion
model, with some explicitly-stated exceptions (see below). The main exception
is that the interpretation of each construct in a generic unit (especially
including the denotation of each name) is determined when the declaration
and body of the generic unit (as opposed to the instance) are compiled,
and in each instance this interpretation is (a copy of) the template
interpretation. In other words, if a construct is interpreted as a name
denoting a declaration D, then in an instance, the copy of the construct
will still be a name, and will still denote D (or a copy of D). From
an implementation point of view, overload resolution is performed on
the template, and not on each copy.
Other properties of the copy (for example, staticness, categories to
which types belong) are recalculated for each instance; this is implied
by the fact that it's a copy.
The interpretation of each construct within a generic
declaration or body is determined using the overloading rules when that
generic declaration or body is compiled. In an instance, the interpretation
of each (copied) construct is the same, except in the case of a name
that denotes the generic_declaration
or some declaration within the generic unit; the corresponding name in
the instance then denotes the corresponding copy of the denoted declaration.
The overloading rules do not apply in the instance.
Although the declarations in the instance are
copies of those in the generic unit, they often have quite different
properties, as explained below. For example a constant declaration in
the generic unit might declare a nonstatic constant, whereas the copy
of that declaration might declare a static constant. This can happen
when the staticness depends on some generic formal.
Since children are considered to occur within
their parent's declarative region, the above rule applies to a name that
denotes a child of a generic unit, or a declaration inside such a child.
Since the Syntax Rules are overloading rules,
it is possible (legal) to violate them in an instance. For example, it
is possible for an instance body to occur in a package_specification
even though the Syntax Rules forbid bodies in package_specification
In an instance, a generic_formal_parameter_declaration
declares a view whose properties are identical to those of the actual,
except when as
specified otherwise (in particular, see 6.1.1,
“Preconditions and Postconditions”, in
Similarly, for a declaration within a generic_formal_parameter_declaration
the corresponding declaration in an instance declares a view whose properties
are identical to the corresponding declaration within the declaration
of the actual.
Ramification: In an instance, there are
no “properties” of types and subtypes that come from the
formal. The primitive operations of the type come from the formal, but
these are declarations in their own right, and are therefore handled
Note that certain properties that come from
the actuals are irrelevant in the instance. For example, if an actual
type is of a class deeper in the derived-type hierarchy than the formal,
it is impossible to call the additional operations of the deeper class
in the instance, because any such call would have to be a copy of some
corresponding call in the generic unit, which would have been illegal.
However, it is sometimes possible to reach into the specification of
the instance from outside, and notice such properties. For example, one
could pass an object declared in the instance specification to one of
the additional operations of the deeper type.
This rule implies, for example, that if a subtype
in a generic unit is a subtype of a generic formal subtype, then the
corresponding subtype in the instance is a subtype of the corresponding
For a generic_instantiation
if a generic actual is a static [(scalar or string)] subtype, then each
use of the corresponding formal parameter within the specification of
the instance is considered to be static. (See AI83-00409.)
Similarly, if a generic actual is a static expression
and the corresponding formal parameter has a static [(scalar or string)]
subtype, then each use of the formal parameter in the specification of
the instance is considered to be static. (See AI83-00505.)
If a primitive
subprogram of a type derived from a generic formal derived tagged type
is not overriding (that is, it is a new subprogram), it is possible for
the copy of that subprogram in an instance to override a subprogram inherited
from the actual. For example:
type T1 is tagged record ... end record;
Formal is new
T1 with private
Derived_From_Formal is new
Formal with record
... end record
Foo(X : in
Derived_From_Formal); -- Does not override anything.
type T2 is new T1 with record ... end record;
procedure Foo(X : in T2);
package Inst is new G(Formal => T2);
In the instance Inst, the declaration of Foo
for Derived_From_Formal overrides the Foo inherited from T2.
For formal types, an implementation that shares the code among multiple
instances of the same generic unit needs to beware that things like parameter
passing mechanisms (by-copy vs. by-reference) and aspect_clause
are determined by the actual.
We allow differences in particular for aspects
that can be specified on generic formal parameters. For instance, Pre
(see 6.1.1) can be specified on generic formal
subprograms to be added to the Pre of the actual.
[Implicit declarations are also copied, and a name
that denotes an implicit declaration in the generic denotes the corresponding
copy in the instance. However, for a type declared within the visible
part of the generic, a whole new set of primitive subprograms is implicitly
declared for use outside the instance, and may differ from the copied
set if the properties of the type in some way depend on the properties
of some actual type specified in the instantiation. For example, if the
type in the generic is derived from a formal private type, then in the
instance the type will inherit subprograms from the corresponding actual
These new implicit declarations
occur immediately after the type declaration in the instance, and override
the copied ones. The copied ones can be called only from within the instance;
the new ones can be called only from outside the instance, although for
tagged types, the body of a new one can be executed by a call to an old
Ramification: The new ones follow from
the class(es) of the formal types. For example, for a type T derived
from a generic formal private type, if the actual is Integer, then the
copy of T in the instance has a "+" primitive operator, which
can be called from outside the instance (assuming T is declared in the
visible part of the instance).
Since an actual type is always in the category determined for the formal,
the new subprograms hide all of the copied ones, except for a declaration
of "/=" that corresponds to an explicit declaration of "=".
Such "/=" operators are special, because unlike other implicit
declarations of primitive subprograms, they do not appear by virtue of
the class, but because of an explicit declaration of "=". If
the declaration of "=" is implicit (and therefore overridden
in the instance), then a corresponding implicitly declared "/="
is also overridden. But if the declaration of "=" is explicit
(and therefore not overridden in the instance), then a corresponding
implicitly declared "/=" is not overridden either, even though
Note that the copied ones can be called from
inside the instance, even though they are hidden from all visibility,
because the names are resolved in the generic unit — visibility
is irrelevant for calls in the instance.
[In the visible part of an instance, an explicit
declaration overrides an implicit declaration if they are homographs,
as described in 8.3
.] On the other hand, an
explicit declaration in the private part of an instance overrides an
implicit declaration in the instance, only if the corresponding explicit
declaration in the generic overrides a corresponding implicit declaration
in the generic. Corresponding rules apply to the other kinds of overriding
described in 8.3
type Ancestor is tagged null record;
type Formal is new Ancestor with private;
package G is
type T is new Formal with null record;
procedure P(X : in T); -- (1)
procedure Q(X : in T); -- (2)
type Actual is new Ancestor with null record;
procedure P(X : in Actual);
procedure Q(X : in Actual);
package Instance is new G(Formal => Actual);
In the instance, the copy of P at (1) overrides
Actual's P, whereas the copy of Q at (2) does not override anything;
in implementation terms, it occupies a separate slot in the type descriptor.
The reason for this rule is so a programmer writing an generic_instantiation _instantiation
need not look at the private part of the generic in order to determine
which subprograms will be overridden.
Recursive generic instantiation is not allowed in
the following sense: if a given generic unit includes an instantiation
of a second generic unit, then the instance generated by this instantiation
shall not include an instance of the first generic unit [(whether this
instance is generated directly, or indirectly by intermediate instantiations)].
Discussion: Note that this rule is not
a violation of the generic contract model, because it is not a Legality
Rule. Some implementations may be able to check this rule at compile
time, but that requires access to all the bodies, so we allow implementations
to check the rule at link time.
For the elaboration of a generic_instantiation
is first evaluated. If a default is used, an implicit generic_association
is assumed for this rule. These evaluations are done in an arbitrary
order, except that the evaluation for a default actual takes place after
the evaluation for another actual if the default includes a name
that denotes the other one.
Finally, the instance
declaration and body are elaborated.
Ramification: Note that if the evaluation
of a default depends on some side effect of some other evaluation, the
order is still arbitrary.
For the evaluation of a generic_association
the generic actual parameter is evaluated. Additional actions are performed
in the case of a formal object of mode in
To be honest:
Actually, the actual is
evaluated only if evaluation is defined for that kind of construct —
we don't actually “evaluate” subtype_mark
5 If a formal type is not tagged, then
the type is treated as an untagged type within the generic body. Deriving
from such a type in a generic body is permitted; the new type does not
get a new tag value, even if the actual is tagged. Overriding operations
for such a derived type cannot be dispatched to from outside the instance.
Ramification: If two overloaded subprograms
declared in a generic package specification differ only by the (formal)
type of their parameters and results, then there exist legal instantiations
for which all calls of these subprograms from outside the instance are
ambiguous. For example:
type A is (<>);
type B is private;
package G is
function Next(X : A) return A;
function Next(X : B) return B;
package P is new G(A => Boolean, B => Boolean);
-- All calls of P.Next are ambiguous.
The following example illustrates some of the subtleties of the substitution
of formals and actuals:
T1 is private
-- A predefined "=" operator is implicitly declared here:
-- function "="(Left, Right : T1) return Boolean;
-- Call this "="1.
T1; -- So we can get our hands on the type from
-- outside an instance.
T2 is new
-- An inherited "=" operator is implicitly declared here:
-- function "="(Left, Right : T2) return Boolean;
-- Call this "="2.
T1_Obj : T1 := ...;
Bool_1 : Boolean := T1_Obj = T1_Obj;
T2_Obj : T2 := ...;
Bool_2 : Boolean := T2_Obj = T2_Obj;
My_Int is new
-- A predefined "=" operator is implicitly declared here:
-- function "="(Left, Right : My_Int) return Boolean;
-- Call this "="3.
"="(X, Y : My_Int) return
-- Call this "="4.
-- "="3 is hidden from all visibility by "="4.
-- Nonetheless, "="3 can “reemerge” in certain circumstances.
I is new
G(T1 => My_Int, ...
); -- "="5 is declared in I (see below).
Another_T1_Obj : S1 := 13; -- Can't denote T1, but S1 will do.
Bool_3 : Boolean := Another_T1_Obj = Another_T1_Obj;
Another_T2_Obj : T2 := 45;
Bool_4 : Boolean := Another_T2_Obj = Another_T2_Obj;
Double : T2 := T2_Obj + Another_T2_Obj;
In the instance I, there is a copy of "="1
(call it "="1i)
(call it "="2i).
declare views of the predefined "=" of My_Int (that is, "="3).
In the initialization of Bool_1 and Bool_2 in the generic unit G, the
names "=" denote "="1
respectively. Therefore, the copies of these names in the instances denote
respectively. Thus, the initialization of I.Bool_1 and I.Bool_2 call
the predefined equality operator of My_Int; they will not call "="4.
The declarations "="1i
are hidden from all visibility. This prevents them from being called
from outside the instance.
The declaration of Bool_3 calls "="4.
The instance I also contains implicit declarations
of the primitive operators of T2, such as "=" (call it "="5)
and "+". These operations cannot be called from within the
instance, but the declaration of Bool_4 calls "="5.
Examples of generic
instantiations (see 12.1):
Swap is new
Exchange(Elem => Integer);
Swap is new
Exchange(Character); -- Swap is overloaded
Square is new
Squaring(Integer); -- "*" of Integer used by default
function Square1 Square is new
Squaring(Item => Matrix, "*" => Matrix_Product);
function Square2 Square is new
Squaring(Matrix, Matrix_Product); -- same as previous
package Int_Vectors is new On_Vectors(Integer, Table, "+");
Examples of uses
of instantiated units:
A := Square(A);
T : Table(1 .. 5) := (10, 20, 30, 40, 50);
N : Integer := Int_Vectors.Sigma(T); -- 150 (see 12.2,
“Generic Bodies” for the body of Sigma)
M : Integer := Sigma(T); -- 150
Inconsistencies With Ada 83
In Ada 83, all explicit
actuals are evaluated before all defaults, and the defaults are evaluated
in the order of the formal declarations. This ordering requirement is
relaxed in Ada 95.
Incompatibilities With Ada 83
We have attempted to remove
every violation of the contract model. Any remaining contract model violations
should be considered bugs in the RM95. The unfortunate property of reverting
to the predefined operators of the actual types is retained for upward
compatibility. (Note that fixing this would require subtype conformance
rules.) However, tagged types do not revert in this sense.
Extensions to Ada 83
Wording Changes from Ada 83
The fact that named associations cannot be used
for two formal subprograms with the same defining name is moved to AARM-only
material, because it is a ramification of other rules, and because it
is not of interest to the average user.
In the explanation that the instance is a copy
of the template, we have left out RM83-12.3(5)'s “apart from the
generic formal part”, because it seems that things in the formal
part still need to exist in instances. This is particularly true for
generic formal packages, where you're sometimes allowed to reach in and
denote the formals of the formal package from outside it. This simplifies
the explanation of what each name in an instance denotes: there are just
two cases: the declaration can be inside or outside (where inside needs
to include the generic unit itself). Note that the RM83 approach of listing
many cases (see RM83-12.5(5-14)) would have become even more unwieldy
with the addition of generic formal packages, and the declarations that
We have corrected the definition of the elaboration
of a generic_instantiation
(RM83-12.3(17)); we don't elaborate entities, and the instance is not
In RM83, there is a rule saying the formal and
actual shall match, and then there is much text defining what it means
to match. Here, we simply state all the latter text as rules. For example,
“A formal foo is matched by an actual greenish bar” becomes
“For a formal foo, the actual shall be a greenish bar.” This
is necessary to split the Name Resolution Rules from the Legality Rules.
Besides, there's really no need to define the concept of matching for
Extensions to Ada 95
Extensions to Ada 2005
Wording Changes from Ada 2005
Added a definition for positional parameters, as this
is missing from Ada 95 and Ada 2005.
Wording Changes from Ada 2012
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe