12.6 Formal Subprograms
[
{generic formal
subprogram} {formal
subprogram, generic} Formal subprograms
can be used to pass callable entities to a generic unit.]
Language Design Principles
Syntax
Reason: There are no null functions because
the return value has to be constructed somehow. We don't allow null for
abstract formal procedures, as the operation is dispatching. It doesn't
seem appropriate (or useful) to say that the implementation of something
is null in the formal type and all possible descendants of that type.
This also would define a dispatching operation that doesn't correspond
to a slot in the tag of the controlling type, which would be a new concept.
Finally, additional rules would be needed to define the meaning of a
dispatching null procedure (for instance, the convention of such a subprogram
should be intrinsic, but that's not what the language says). It doesn't
seem worth the effort.
Name Resolution Rules
{expected profile
(formal subprogram default_name) [partial]} The
expected profile for the
default_name,
if any, is that of the formal subprogram.
Ramification: This rule, unlike others
in this clause, is observed at compile time of the
generic_declaration.
{expected profile
(formal subprogram actual) [partial]} For
a generic formal subprogram, the expected profile for the actual is that
of the formal subprogram.
Legality Rules
The profiles of the formal and any named default
shall be mode-conformant.
{mode conformance
(required)}
Ramification: This rule, unlike others
in this clause, is checked at compile time of the
generic_declaration.
The profiles of the formal and actual shall be mode-conformant.
{mode conformance (required)}
if the actual matching the
formal_subprogram_declaration
denotes a generic formal object of another generic unit
G, and
the instantiation containing the actual that occurs within the body of
a generic unit
G or within the body of a generic unit declared
within the declarative region of the generic unit
G, then the
corresponding parameter or result type of the formal subprogram of
G
shall have a
null_exclusion;
otherwise, the subtype of the corresponding parameter
or result type of the actual matching the
formal_subprogram_declaration
shall exclude null.
{generic contract
issue [partial]} In addition to the places
where Legality Rules normally apply (see
12.3),
this rule applies also in the private part of an instance of a generic
unit.
Reason: This
rule prevents “lying”.
Null must never be the value
of a parameter or result with an explicit
null_exclusion.
The first bullet is an assume-the-worst rule which prevents trouble in
generic bodies (including bodies of child generics) when the formal subtype
excludes null implicitly.
Ramification: The specific tagged type
could be any of a formal tagged private type, a formal derived type,
a formal interface type, or a normal tagged type. While the last case
doesn't seem to be very useful, there isn't any good reason for disallowing
it. This rule ensures that the operation is a dispatching operation of
some type, and that we unambiguously know what that type is.
We informally call a subprogram declared by
a
formal_abstract_subprogram_declaration
an
abstract formal subprogram, but we do not use this term in
normative wording. {
abstract formal subprogram}
(We
do use it often in these notes.)
Ramification:
This means that the actual is either a primitive operation of the
controlling type, or an abstract formal subprogram. Also note that this
prevents the controlling type from being class-wide (with one exception
explained below), as only specific types have primitive operations (and
a formal subprogram eventually has to have an actual that is a primitive
of some type). This could happen in a case like:
generic
type T(<>) is tagged private;
with procedure Foo (Obj : in T) is abstract;
package P ...
package New_P is new P (Something'Class, Some_Proc);
The instantiation here is always illegal, because
Some_Proc could never be a primitive operation of Something'Class (there
are no such operations). That's good, because we want calls to Foo always
to be dispatching calls.
Since it is possible
for a formal tagged type to be instantiated with a class-wide type, it
is possible for the (real) controlling type to be class-wide in one unusual
case:
generic
type NT(<>) is new T with private;
-- Presume that T has the following primitive operation:
-- with procedure Bar (Obj : in T);
package Gr ...
package body Gr is
package New_P2 is new P (NT, Foo => Bar);
end Gr;
package New_Gr is new Gr (Something'Class);
The instantiation of New_P2 is legal, since
Bar is a dispatching operation of the actual type of the controlling
type of the abstract formal subprogram Foo. This is not a problem, since
the rules given in
12.5.1 explain how this
routine dispatches even though its parameter is class-wide.
Note that this legality rule never needs to
be rechecked in an instance (that contains a nested instantiation). The
rule only talks about the actual type of the instantiation; it does not
require looking further; if the actual type is in fact a formal type,
we do not intend looking at the actual for that formal.
Static Semantics
A
formal_subprogram_declaration
declares a generic formal subprogram. The types of the formal parameters
and result, if any, of the formal subprogram are those determined by
the
subtype_marks
given in the
formal_subprogram_declaration;
however, independent of the particular subtypes that are denoted by the
subtype_marks,
the nominal subtypes of the formal parameters and result, if any, are
defined to be nonstatic, and unconstrained if of an array type [(no applicable
index constraint is provided in a call on a formal subprogram)]. In an
instance, a
formal_subprogram_declaration
declares a view of the actual. The profile of this view takes its subtypes
and calling convention from the original profile of the actual entity,
while taking the formal parameter
names
and
default_expressions
from the profile given in the
formal_subprogram_declaration.
The view is a function or procedure, never an entry.
Discussion: This rule is intended to
be the same as the one for renamings-as-declarations, where the
formal_subprogram_declaration
is analogous to a renaming-as-declaration, and the actual is analogous
to the renamed view.
If a generic unit has a
subprogram_default
specified by a box, and the corresponding actual parameter is omitted,
then it is equivalent to an explicit actual parameter that is a usage
name identical to the defining name of the formal.
Reason: This is necessary to trigger
all of the dispatching operation rules. It otherwise would not be considered
a dispatching operation, as formal subprograms are never primitive operations.
13 The matching rules for formal subprograms
state requirements that are similar to those applying to
subprogram_renaming_declarations
(see
8.5.4). In particular, the name of a
parameter of the formal subprogram need not be the same as that of the
corresponding parameter of the actual subprogram; similarly, for these
parameters,
default_expressions
need not correspond.
14 The constraints that apply to a parameter
of a formal subprogram are those of the corresponding formal parameter
of the matching actual subprogram (not those implied by the corresponding
subtype_mark
in the
_specification of the formal subprogram).
A similar remark applies to the result of a function. Therefore, to avoid
confusion, it is recommended that the
name
of a first subtype be used in any declaration of a formal subprogram.
15 The subtype specified for a formal parameter
of a generic formal subprogram can be any visible subtype, including
a generic formal subtype of the same
generic_formal_part.
16 A formal subprogram is matched by an
attribute of a type if the attribute is a function with a matching specification.
An enumeration literal of a given type matches a parameterless formal
function whose result type is the given type.
17 A
default_name
denotes an entity that is visible or directly visible at the place of
the
generic_declaration;
a box used as a default is equivalent to a name that denotes an entity
that is directly visible at the place of the
_instantiation.
Proof: Visibility and name resolution
are applied to the equivalent explicit actual parameter.
20 {
AI95-00348-01}
A null procedure as a subprogram default has convention Intrinsic (see
6.3.1).
Proof: This is an implicitly declared
subprogram, so it has convention Intrinsic as defined in
6.3.1.
Examples
Examples of generic
formal subprograms:
{
AI95-00433-01}
with function "+"(X, Y : Item)
return Item
is <>;
with function Image(X : Enum)
return String
is Enum'Image;
with procedure Update
is Default_Update;
with procedure Pre_Action(X :
in Item)
is null; --
defaults to no action
with procedure Write(S :
not null access Root_Stream_Type'Class;
Desc : Descriptor)
is abstract Descriptor'Write; --
see 13.13.2
--
Dispatching operation on Descriptor with default
-- given the generic procedure declaration
generic
with procedure Action (X : in Item);
procedure Iterate(Seq : in Item_Sequence);
-- and the procedure
procedure Put_Item(X : in Item);
-- the following instantiation is possible
procedure Put_List is new Iterate(Action => Put_Item);
Extensions to Ada 95
{
AI95-00348-01}
The formal subprogram default of
null is new. It allows the default
of a generic procedure to do nothing, such as for passing a debugging
routine.
Wording Changes from Ada 95