!standard 4.3(4/5) 22-01-26 AI22-0032-1/01 !standard 4.3.5(11/5) !class binding interpretation 22-01-26 !status work item 22-01-26 !status received 21-11-09 !priority Low !difficulty Easy !qualifier Omission !subject Abstract and classwide 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. !question (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 names 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. AARM Ramification: Since the Aggregate aspect is nonoverriddable, this rule is rechecked on any derived type that inherits an Aggregate aspect. This rule also 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_expressions). 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 anonynous 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 non-abstract tagged 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. One could argue that if following the Dynamic Semantics definition for an aggregate makes the aggregate illegal if that definition generates an illegal call. However, generally a Dynamic Semantics definition (even an equivalence, and container aggregates are not defined as an equivalence) does not imply an Legality Rules or Static Semantic rules, as these latter rules depend on the views of entities, while Dynamic Semantics rules almost never depend on the view. Moreover, we 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 using 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 nonoveriddable 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. !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 ****************************************************************