Version 1.4 of ai22s/ai22-0032-1.txt
!standard 4.3(4/5) 22-02-04 AI22-0032-1/04
!standard 4.3.5(11/5)
!class binding interpretation 22-01-26
!status Corrigendum 1-2022 22-02-03
!status ARG Approved 16-0-0 22-02-03
!status work item 22-01-26
!status received 21-11-09
!priority Low
!difficulty Easy
!qualifier Omission
!subject Abstract and class-wide container aggregates
!summary
Class-wide container aggregates are not allowed.
If the container type of an Aggregate aspect is not abstract, none of the
subprograms specified in the Aggregate aspect can be abstract.
!issue
(1) 4.3(4/5) disallows record and extension aggregates from being class-wide,
but does not disallow class-wide aggregates of other kinds. Should container
aggregates be allowed to be class-wide? (No.)
(2) Nothing in 4.3.5 disallows a subprogram specified in an Aggregate aspect
from being abstract. Obviously, we do not want an aggregate whose
implementation would call an abstract subprogram (we never want to call an
abstract subprogram). Is there a rule missing here? (Yes.)
!recommendation
(See Summary.)
!wording
(1) Modify 4.3(4/5):
A record_aggregate{,}[ or] extension_aggregate{, or container_aggregate}
shall not be of a class-wide type.
(2) Add after 4.3.5(11/5):
If the container type T is not abstract, then none of the subprograms
specified in the Aggregate aspect for T shall be abstract.
AARM Ramification: Since the Aggregate aspect is nonoverridable, this
rule is rechecked on any derived type that inherits an Aggregate aspect.
In addition to the places where Legality Rules normally apply (see 12.3),
these rules apply also in the private part of an instance of a generic unit.
AARM Ramification: The first Legality Rule has to be rechecked in
instances, if a type with an Aggregate aspect is derived from a formal
private type, in case the actual type for the private type is an array
type. The last Legality Rule has to be rechecked in instances, in case
an actual type for an abstract formal type is not abstract.
!discussion
(1) 4.3(4) originally disallowed all aggregates from being class-wide. It was
modified for Ada 2022 to allow delta_aggregates to be of a class-wide type (as
the specific type can be retrieved from the base_expression). The rule
didn't need to mention array_aggregates as those cannot be class-wide anyway.
But the change was made before container_aggregates were defined, and it was
forgotten to disallow those.
It would be possible to support class-wide container aggregates, by treating
them as tag-indeterminate and using the usual rules for tag-indeterminate
functions to determine the tag for the anonymous object. Then, one would use
dispatching calls on the subprograms (which are already required to be
primitive, so no incompatibility would be introduced) to implement the
aggregate. This seems like an extension rather than a fix, so we leave it
for a future language update and disallow class-wide container aggregates for
now.
(2) The rules for abstract operations make it illegal for a nonabstract
tagged type to have any abstract operations. However, since the Aggregate
aspect is allowed on any non-array type, abstract operations are possible if
the type is not tagged. We surely do not want to have an aggregate calling
abstract routines.
We also have a language design principle that if every use of some
definition would be illegal, then the definition itself is illegal. (One
example is a Pure generic unit; if no instantiation of the unit could be
declared Pure, the generic unit is illegal.) This means we want the Aggregate
aspect to be illegal if any container aggregate would be illegal by making
illegal calls.
for all of these reasons, we need an explicit rule to ban abstract subprograms
from being used in an Aggregate aspect for a nonabstract type. Note that we
do not need an additional rule to ban this for any derived type that inherits
the Aggregate aspect, as this aspect is nonoverridable, and the Legality Rules
associated with a nonoverridable aspect are rechecked for each derived type
that inherits the aspect (by 13.1.1(18.3/5)).
Note that it is OK to have abstract routines if the type itself is abstract;
in that case, no aggregate can be written (as abstract aggregates are banned
by 3.9.3(8/5)). It's unclear if this would be a useful construct, but since
there is no semantic problem, there seems to be no reason to ban it.
!corrigendum 4.3(4/5)
Replace the paragraph:
A record_aggregate or extension_aggregate shall not be of a
class-wide type.
by:
A record_aggregate, extension_aggregate, or container_aggregate
shall not be of a class-wide type.
!corrigendum 4.3.5(11/5)
Insert after the paragraph:
For an Aggregate aspect, the key type of Assign_Indexed shall be the same
type as that of the parameters of New_Indexed. Additionally, if both
Add_Unnamed and Assign_Indexed are specified, the final parameters shall
be of the same type — the element type of the container type.
the new paragraph:
If the container type T is not abstract, then none of the subprograms
specified in the Aggregate aspect for T shall be abstract.
In addition to the places where Legality Rules normally apply (see 12.3),
these rules apply also in the private part of an instance of a generic unit.
!ACATS test
ACATS B-Test(s) should check that both of these rules are enforced (and in the
case of the abstract routines, also are enforced for [untagged] derived types).
!appendix
From: The Editor - February 4th, 2022
I happened to notice that the first Legality Rule of 4.3.5 also could need
rechecking in an instance. Therefore, I put the generic boilerplate into a
separate paragraph and split and updated the AARM note appropriately. Consider
this my editorial review.
****************************************************************
Questions? Ask the ACAA Technical Agent