3.10.1 Incomplete Type Declarations
There are no particular limitations on the designated
type of an access type. In particular, the type of a component of the
designated type can be another access type, or even the same access type.
This permits mutually dependent and recursive access types. An incomplete_type_declaration
can be used to introduce a type to be used as a designated type, while
deferring its full definition to a subsequent full_type_declaration
Given an access type A whose designated
type T is an incomplete view, a dereference of a value of type
A also has this incomplete view except when:
Whether the designated type is an incomplete view
(and thus whether this set of rules applies) is determined by the view
of the type at the declaration of the access type; it does not change
during the life of the type.
it occurs within the immediate
scope of the completion of T, or
In these cases, the dereference has the full
view of T visible at the point of the dereference.
We need the “in whose visible part” rule so that the
second rule doesn't trigger in the body of a package with a with
of a child unit:
package P is
type PtrT is access T;
private package P.C is
Ptr : PtrT;
package body P is
-- Ptr.all'Size is not legal here, but we are within it is in the scope
-- of a nonlimited_with_clause for P.
type T is ...
-- Ptr.all'Size is legal here.
This is implied by the next AARM-only
rule, plus the rules in 3.11.1
” which require a completion to appear later
and immediately within the same declarative region.
To be honest:
If the implementation supports
it, an incomplete_type_declaration
can be imported (using aspect Import, see B.1),
in which case no explicit completion is allowed completed
by a pragma
We now allow discriminant_constraint
even if the full type is deferred to the package body. However, there
is no particular implementation burden because we have dropped the concept
of the dependent compatibility check. In other words, we have effectively
This allows, for example, a record to have a component
designating a subprogram that takes that same record type as a parameter.
not in the profile for a body or entry.
as a generic actual parameter whose corresponding
generic formal parameter is a formal incomplete type (see 12.5.1).
If such a name
denotes a tagged incomplete view, it may also be used:
This is to prevent children from imposing requirements
on their ancestor library units for deferred incomplete types.
paragraph was deleted.
such a name
occurs within the declaration list containing the completion of the incomplete
view, it may also be used:
was deleted.Reason: This
allows, for example, a record to have a component designating a subprogram
that takes that same record type as a parameter.
If any of the above uses occurs as part of the
declaration of a primitive subprogram of the incomplete view, and the
declaration occurs immediately within the private part of a package,
then the completion of the incomplete view shall also occur immediately
within the private part; it shall not be deferred to the package body.
Reason: This fixes
a hole in Ada 95 where a dispatching operation with an access parameter
could be declared in a private part and a dispatching call on it could
occur in a child even though there is no visibility on the full type,
requiring access to the controlling tag without access to the representation
of the type.
No other uses of a name
that denotes an incomplete view of a type are allowed.
that denotes an object A dereference (whether
implicit or explicit — see 4.1)
shall not be of an incomplete view type
. An actual parameter in a call shall not be of an untagged incomplete
view. The result object of a function call shall not be of an incomplete
view. A prefix
shall not denote a subprogram having a formal parameter of an untagged
incomplete view, nor a return type that is an incomplete view.
Reason: We used
to disallow all dereferences of an incomplete type. Now we only disallow
such dereferences when used as a prefix.
Dereferences used in other contexts do not pose a problem since normal
type matching will preclude their use except when the full type is “nearby”
as context (for example, as the expected type).
This also disallows prefixes
that are directly of an incomplete view. For instance, a parameter P
can be declared of a tagged incomplete type, but we don't want to allow
P'Size, P'Alignment, or the like, as representation values
aren't known for an incomplete view.
We say “denotes
an object” so that prefixes that directly name an incomplete view
are not covered; the previous rules cover such cases, and we certainly
don't want to ban Incomp'Class.
As subprogram profiles now may include any kind
of incomplete type, we also disallow passing objects of untagged incomplete
types in subprogram calls (as the parameter passing method is not known
as it is for tagged types) and disallow returning any sort of incomplete
objects (since we don't know how big they are).
Reason: An incomplete type has no real
existence, so it doesn't need to be "created" in the usual
sense we do for other types. It is roughly equivalent to a "forward;"
declaration in Pascal. Private types are different, because they have
a different set of characteristics from their full type.
that denotes an object of an incomplete view is defined to be of a limited
type. Hence, the target of an assignment statement shall not be of an
Example of a recursive
type Cell; -- incomplete type declaration
type Link is access Cell;
type Cell is
Value : Integer;
Succ : Link;
Pred : Link;
Head : Link := new Cell'(0, null, null);
Next : Link := Head.Succ;
Examples of mutually dependent access types:
Person(<>); -- incomplete type declaration
Car is tagged;;
-- incomplete type declaration
Person_Name is access
Car_Name is access all
Car is tagged
Number : Integer;
Owner : Person_Name;
type Person(Sex : Gender) is
Name : String(1 .. 20);
Birth : Date;
Age : Integer range 0 .. 130;
Vehicle : Car_Name;
case Sex is
when M => Wife : Person_Name(Sex => F);
when F => Husband : Person_Name(Sex => M);
My_Car, Your_Car, Next_Car : Car_Name := new
Car; -- see 4.8
George : Person_Name := new
George.Vehicle := Your_Car;
Extensions to Ada 83
may be applied to an incomplete type, even if it
its completion is deferred to the package body, because there
is no “dependent compatibility check” required any more.
Of course, the constraint can be specified only if a known_discriminant_part
was given in the incomplete_type_declaration
As mentioned in the previous paragraph, that is no longer required even
when the full type has discriminants.
Wording Changes from Ada 83
incomplete types were not explicitly disallowed in RM83, though AI83-00039
indicated that it was not strictly necessary since troublesome cases
would result in Constraint_Error at run time, since the access value
would necessarily be null. However, this introduces an undesirable implementation
burden, as illustrated by Example 4 of AI83-00039:
package Pack is
type Pri is private;
type Pri is access Sep;
X : Pri;
package body Pack is -- Could be separately compiled!
type Sep is ...;
X := new Sep;
private package Pack.Child is
I : Integer := X.all'Size; -- Legal, by AI-00039.
Generating code for the above example could
be a serious implementation burden, since it would require all aliased
objects to store size dope, and for that dope to be in the same format
for all kinds of types (or some other equivalently inefficient implementation).
On the contrary, most implementations allocate dope differently (or not
at all) for different designated subtypes.
Incompatibilities With Ada 95
It is now illegal to use an
incomplete view (type) as the parameter or result of an access-to-subprogram
type unless the incomplete view is completed in the same declaration
list as the use. This was allowed in Ada 95 for incomplete types where
the completion was deferred to the body. By disallowing this rare use
of incomplete views, we can allow the use of incomplete views in many
more places, which is especially valuable for limited views.
It is now illegal to use an incomplete view (type)
in a primitive subprogram of the type unless the incomplete view is completed
in the package specification. This was allowed in Ada 95 for incomplete
types where the completion was deferred to the body (the use would have
to be in an access parameter). This incompatibility was caused by the
fix for the hole noted in Legality Rules above.
Extensions to Ada 95
Tagged incomplete types are
new. They are allowed in parameter declarations as well as the usual
places, as tagged types are always by-reference types (and thus there
can be no code generation issue).
Wording Changes from Ada 95
The description of incomplete types as incomplete
views is new. Ada 95 defined these as separate types, but neglected
to give any rules for matching them with other types. Luckily, implementers
did the right thing anyway. This change also makes it easier to describe
the meaning of a limited view.
Extensions to Ada 2005
Correction: Fixed the
definition so that an anonymous access-to-subprogram type can use an
incomplete view in the same way that a named access-to-subprogram type
Incomplete types now can be used in subprogram
declarations. The type has to be complete before any calls or the body
is declared. This reduces the places where access types are required
for types imported from limited views of packages.
Incomplete types now can be completed by private
types and private extensions. Since this can already happen for limited
views, there is no remaining reason to disallow it for explicitly declared
Wording Changes from Ada 2005
Correction: Changed the rules of uses of
dereferences of incomplete views such that it does not introduce an unintentional
incompatibility with Ada 83 and Ada 95.
Incomplete types now can be used as actuals to
formal incomplete types (see 12.5.1).
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe