12.5.1 Formal Private and Derived Types
1/2
{
AI95-00442-01}
[
In its most general form, the category The
class determined for a formal private type
is
all types, but it can be restricted to only nonlimited types or to only
tagged types can be either limited or nonlimited,
and either tagged or untagged; no more specific class is known for such
a type. The
category class
determined for a formal derived type is the derivation class rooted at
the ancestor type.]
1.a/2
Proof: {
AI95-00442-01}
The first rule is given normatively below, and
the second rule is given normatively in 12.5;
they are repeated here to give a capsule summary of what this subclause
is about.
Syntax
2
formal_private_type_definition ::= [[
abstract]
tagged] [
limited]
private
3/2
Legality Rules
4
If a generic formal type declaration has a known_discriminant_part,
then it shall not include a default_expression
for a discriminant.
4.a
Ramification: Consequently, a generic
formal subtype with a 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.
5/2
{
AI95-00401-01}
{
AI95-00419-01}
{
AI95-00443-01}
{ancestor subtype (of a formal derived
type)} {private
extension [partial]} 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 word
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.
5.a
Reason: We use the term “ancestor”
here instead of “parent” because the actual can be any descendant
of the ancestor, not necessarily a direct descendant.
5.b/2
{
AI95-00419-01}
We require the ancestor type to be limited when
limited appears so that we avoid oddies like limited integer types.
Normally, limited means “match anything” for a generic
formal, but it was felt that allowing limited elementary types to be
declared was just too weird. Integer still matches a formal limited private
type; it is only a problem when the type is known to be elementary. Note
that the progenitors are required to be limited by rules in 3.9.4,
thus that part of the rule is redundant.
5.c/2
{
AI95-00443-01}
We require that synchronized appear if the
ancestor or any of the progenitors are synchronized, so that property
is explicitly given in the program text – it is not automatically
inherited from the ancestors. However, it can be given even if neither
the ancestor nor the progenitors are synchronized.
5.1/2
{
AI95-00251-01}
{
AI95-00401-01}
{
AI95-00443-01}
The actual type for a formal derived type shall
be a descendant of [the ancestor type and] every progenitor of the formal
type. If the reserved word synchronized appears in the declaration
of the formal derived type, the actual type shall be a synchronized tagged
type.
5.d/2
Proof: The actual
type has to be a descendant of the ancestor type, in order that it be
in the correct class. Thus, that part of the rule is redundant.
5.e/2
Discussion: For
a non-formal private extension, we require the partial view to be synchronized
if the full view is synchronized tagged. This does not apply to a formal
private extension — it is OK if the formal is not synchronized.
Any attempt to extend the formal type will be rechecked in the instance,
where the rule disallowing extending a sychronized non-interface type
will be enforced. This is consistent with the “no hidden interfaces”
rule also applying only to non-formal private extensions, as well as
the rule that a limited non-formal private extension implies a limited
full type. Formal private extensions are exempted from all these rules
to enable the construction of generics that can be used with the widest
possible range of types. In particular, an indefinite tagged limited
formal private type can match any “concrete” actual tagged
type.
6
If the formal subtype is definite, then the actual
subtype shall also be definite.
6.a
Ramification: On the other hand, for
an indefinite formal subtype, the actual can be either definite or indefinite.
7
For a generic formal
derived type with no discriminant_part:
8
- If the ancestor subtype is constrained,
the actual subtype shall be constrained, and shall be statically compatible
with the ancestor;
8.a
Ramification: In other words, any constraint
on the ancestor subtype is considered part of the “contract.”
9
- If the ancestor subtype is an unconstrained
access or composite subtype, the actual subtype shall be unconstrained.
9.a
Reason: This rule ensures that if a composite
constraint is allowed on the formal, one is also allowed on the actual.
If the ancestor subtype is an unconstrained scalar subtype, the actual
is allowed to be constrained, since a scalar constraint does not cause
further constraints to be illegal.
10
- 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.
10.a
Reason: This ensures that if a discriminant
constraint is given on the formal subtype, the corresponding constraint
in the instance will make sense, without additional run-time checks.
This is not necessary for arrays, since the bounds cannot be overridden
in a type extension. An unknown_discriminant_part
may be used to relax these matching requirements.
10.1/2
- {AI95-00231-01}
If the ancestor subtype is an access subtype, the
actual subtype shall exclude null if and only if the ancestor subtype
excludes null.
10.b/2
Reason: We require
that the “excludes null” property match, because it would
be difficult to write a correct generic for a formal access type without
knowing this property. Many typical algorithms and techniques will not
work for a subtype that excludes null (setting an unused component to
null, default-initialized objects, and so on). We want this sort
of requirement to be reflected in the contract of the generic.
11
The declaration of
a formal derived type shall not have a known_discriminant_part.
For a generic formal private type with a known_discriminant_part:
12
- The actual type shall be a type with
the same number of discriminants.
13
- The actual subtype shall be unconstrained.
14
- The subtype of each discriminant of
the actual type shall statically match the subtype of the corresponding
discriminant of the formal type. {statically
matching (required) [partial]}
14.a
Reason: We considered defining the first
and third rule to be called “subtype conformance” for discriminant_parts.
We rejected that idea, because it would require implicit (inherited)
discriminant_parts, which seemed like too
much mechanism.
15
[For a generic formal type with an unknown_discriminant_part,
the actual may, but need not, have discriminants, and may be definite
or indefinite.]
Static Semantics
16/2
{
AI95-00442-01}
The
category class
determined for a formal private type is as follows:
17/2
Type Definition Determined Category Class
limited private the category class of all types
private the category class of all nonlimited types
tagged limited private the category class of all tagged types
tagged private the category class of all nonlimited tagged types
18
[The presence of the reserved word abstract
determines whether the actual type may be abstract.]
19
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.]
20/2
{
AI95-00233-01}
If the ancestor type is a composite type that is not an array type, the
formal type inherits components from the ancestor type (including discriminants
if a new
discriminant_part is not specified),
as for a derived type defined by a
derived_type_definition
(see
3.4 and 7.3.1).
21/2
{
8652/0038}
{
AI95-00202}
{
AI95-00233-01}
{
AI95-00401-01}
For a formal derived type, the predefined operators and inherited user-defined
subprograms are determined by the ancestor type
and any progenitor types, and are implicitly declared at the earliest
place, if any,
immediately within the declarative
region in which within the immediate scope
of the formal type
is declared, where
the corresponding primitive subprogram of the ancestor
or
progenitor is visible (see
7.3.1).
In an instance, the copy of such an implicit declaration 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.
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.]
21.a/2
Ramification: {
AI95-00401-01}
The above rule defining the properties of primitive subprograms in an
instance applies even if the subprogram has been overridden or hidden
for the actual type. This rule is necessary for untagged types, because
their primitive subprograms might have been overridden by operations
that are not subtype-conformant with the operations defined for the class.
For tagged types, the rule still applies, but the primitive subprograms
will dispatch to the appropriate implementation based on the type and
tag of the operands. Even for tagged types, the formal parameter names
and
default_expressions are determined by
those of the primitive subprograms of the specified ancestor type
(or progenitor type, for subprograms inherited from an interface type).
22/1
For a prefix prefix
S that denotes a formal indefinite subtype, the following attribute is
defined:
23
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.
23.a/2
Discussion: {
AI95-00114-01}
Whether an actual subtype is definite or indefinite may have a major
effect on the algorithm used in a generic. For example, in a generic
I/O package, whether to use fixed-length or variable-length records could
depend on whether the actual is definite or indefinite. This attribute
is essentially a replacement for the Constrained attribute
,
which is now considered obsolete.
Dynamic Semantics
23.1/2
{
AI95-00158-01}
In the case where a formal type is tagged with
unknown discriminants, and the actual type is a class-wide type T'Class:
23.2/2
- {AI95-00158-01}
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.
23.3/2
- {AI95-00158-01}
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. {Program_Error
(raised by failure of run-time check)}
23.b/2
Discussion: As
it states in 6.3.1, the convention of an
inherited subprogram of a generic formal tagged type with unknown discriminants
is intrinsic.
23.c/2
In
the case of a corresponding primitive of T with no controlling formal
parameters, the context of the call provides the controlling tag value
for the dispatch. If no tag is provided by context, Program_Error is
raised rather than resorting to a nondispatching call. For example:
23.d/2
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/2
package 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/2
type T1 is new T with null record;
package I is new G(T1'Class);
24/2
9 {
AI95-00442-01}
In accordance with the general rule that the actual type shall belong
to the
category class
determined for the formal (see
12.5, “
Formal
Types”):
25
- If the formal type is nonlimited,
then so shall be the actual;
26
- For a formal derived type, the
actual shall be in the class rooted at the ancestor subtype.
27
10 The actual type can be abstract only
if the formal type is abstract (see
3.9.3).
27.a
Reason: This is necessary to avoid contract
model problems, since one or more of its primitive subprograms are abstract;
it is forbidden to create objects of the type, or to declare functions
returning the type.
27.b
Ramification: On the other hand, it is
OK to pass a non-abstract actual to an abstract formal — abstract
on the formal indicates that the actual might be abstract.
28
11 If the formal has a discriminant_part,
the actual can be either definite or indefinite. Otherwise, the actual
has to be definite.
Incompatibilities With Ada 83
28.a
{
incompatibilities with Ada 83}
Ada
83 does not have
unknown_discriminant_parts,
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.
28.b
The check for discriminant subtype matching
is changed from a run-time check to a compile-time check.
Extensions to Ada 95
28.c/2
{
AI95-00251-01}
{
AI95-00401-01}
{
AI95-00419-01}
{
AI95-00443-01}
{extensions to Ada 95} A
generic formal derived type can include progenitors (interfaces) as well
as a primary ancestor. It also may include limited to indicate
that it is a limited type, and synchronized to indicate that it
is a synchronized type.
Wording Changes from Ada 95
28.d/2
{
8652/0038}
{
AI95-00202-01}
Corrigendum: Corrected wording to define
the operations that are inherited when the ancestor of a formal type
is itself a formal type to avoid anomalies.
28.e/2
{
AI95-00158-01}
Added a semantic description of the meaning of
operations of an actual class-wide type, as such a type does not have
primitive operations of its own.
28.f/2
{
AI95-00231-01}
Added a matching rule for access subtypes that
exclude null.
28.g/2
{
AI95-00233-01}
The wording for the declaration of implicit operations
is corrected to be consistent with 7.3.1
as modified by Corrigendum 1.
28.h/2
{
AI95-00442-01}
We change to “determines a category”
as that is the new terminology (it avoids confusion, since not all interesting
properties form a class).