Version 1.1 of ais/ai-00391.txt

Unformatted version of ais/ai-00391.txt version 1.1
Other versions for file ais/ai-00391.txt

!standard 03.09.03 (04)          04-11-13 AI95-00391/01
!standard 03.04 (27)
!standard 03.09.01 (04)
!standard 03.09.03 (06)
!class amendment 04-11-13
!status work item 04-11-13
!status received 04-11-13
!priority Medium
!difficulty Hard
!subject Functions with controlling results in null extensions
!summary
If a type extension is a record extension with a null extension part, and no new discriminant part, then primitive functions with controlling results do not need to be overridden. The result of calling an implicitly declared inherited function with a controlling result is an extension aggregate with a null extension part.
!problem
type derivation is commonly used after a package instantation that declares a new type, to redeclare the new type in the scope enclosing the instantiation.
For example
package T_Sets is new Sets(T); type T_Set is new T_Sets.Set;
Unfortunately, this paradigm does not work if the type is tagged and has one or more functions with controlling results. For example, this does not work:
generic with type Element is private; package Sets is type Set is tagged private; function Unit_Set(E : Element) return Set; ... end Sets;
package T_Sets is new Sets(T); type T_Set is new T_Sets.Set with null record; -- This is illegal unless Unit_Set is overridden here
This is unpleasant. The programmer just wants to use the type, but they want it declared in the current scope, rather than inside the instantiation. Because of this, they are forced to override each of the functions with controlling results even though they have not added any components nor changed the type in any significant way.
!proposal
There are various possible solutions. One would be a kind of "type rename" clause which would implicitly declare renames of all of the primitive subprograms of the type as well.
However, that wouldn't address the more general issue of a null extension of a type, and the unnecessary burden of having to override all of the functions with controlling results.
The more straightforward solution is to drop the requirement to override functions with controlling results when the derived type is a "null extension" -- no components in the extension part, and no new discriminant part. One could take it further to allow a new discriminant part, so long as the discriminants are associated one-for-one with the existing discriminants. It's not clear that this last capability would be worth the effort, so we haven't included it here. It would clearly be feasible to add this capability at a later date, or during ARG review.
!wording
Modify 3.4(27) as follows:
... If the result type of the inherited subprogram is the derived type, the result of calling the parent's subprogram is converted to the derived type{, or in the case of a null extension, extended to the derived type with an extension_aggregate of the form:
(parent_function_result with null record)
}
Add after 3.9.1(4):
Static Semantics
A record extension is a null extension if its declaration has no known_discriminant_part and its record_extension_part includes no component_declarations.
Modify 3.9.3(4) of AI-251:
If a type inherits a subprogram corresponding to an abstract subprogram{, or a type other than a null extension inherits} [or to] a function with a controlling result, then:
Modify 3.9.3(4):
* Otherwise, the subprogram shall be overridden with a nonabstract subprogram {or, in the case of a private extension inheriting a function with a controlling result, have a full type that is a null extension}; ...
!discussion
This problem seems important to fix, especially as we are defining standard "container" packages which declare tagged types. Having to override functions with controlling results for null extensions is a nuisance.
One could go farther and eliminate the requirement for overriding functions with controlling results if all new components had explicit defaults, but that seems a potential source of errors. With null extensions, the likelihood of an automatically provided overriding being inappropriate seems miniscule.
Although we don't talk about a "wrapper," we anticipate that most implementations will need to provide them, since the caller will not be aware they need to change the tag of the result returned by the function when the function is reached via a dispatching call. Clearly the wrapper will be trivial, analogous to the kind of wrapper often created for a renaming-as-body. A null extension aggregate essentially just changes the tag of its ancestor_part.
!example
(** Missing **)
--!corrigendum
!ACATS test
ACATS tests need to be constructed to test this feature.
!appendix

****************************************************************

Questions? Ask the ACAA Technical Agent