Version 1.5 of ai22s/ai22-0027-1.txt

Unformatted version of ai22s/ai22-0027-1.txt version 1.5
Other versions for file ai22s/ai22-0027-1.txt

!standard 3.4.1(5)          22-06-23 AI22-0027-1/04
!standard 4.5.2(28.1/5)
!standard 12.5.1(23.2/2)
!standard 12.6(9.2/3)
!class binding interpretation 22-01-24
!status Corrigendum 1-2022 22-06-23
!status WG9 Approved 22-10-18
!status ARG Approved 15-0-0 22-06-23
!status work item 22-01-24
!status received 21-11-18
!priority Low
!difficulty Easy
!qualifier Omission
!subject Primitive equality of a class-wide type
!summary
The primitive equality of a class-wide type T'Class is implemented by a dispatching call on the primitive equality of T.
!issue
What is the "primitive equality" for a class-wide type? This term is used in 4.5.2(28.1/5) describing the semantics of membership, where it says:
... If the tested type is a record type or a record extension, or is limited at the point where the membership test occurs, the test uses the primitive equality for the type; otherwise, the test uses predefined equality. ...
If the tested type is a class-wide type, we need to call the primitive equality of the class-wide type. But 3.4.1(5) says that class-wide types have no primitive subprograms of their own. So what is called here??
!recommendation
(See Summary.)
!wording
Add after 3.4.1(5):
When a language rule references a given primitive operation of a type, in the case of a class-wide type T'Class, this is equivalent to 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.
Add after AARM 4.5.2(28.a/5):
AARM Ramification: If the tested type is class-wide, "primitive equality" is interpreted as described in 3.4.1. Specifically, it is implemented by a dispatching call on the primitive equality of the specific type associated with the class-wide type.
[Editor's note: The following modifications are to take existing explicit descriptions and change them to depend on the general description now added to 3.4.1.]
Modify 12.5.1(23.2/2):
* 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 {as described in 3.4.1 for primitive operations of a class-wide type}[(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].
Modify 12.6(9.2/3):
For each primitive subprogram of T that is directly visible at the point of the instantiation, and that has at least one controlling formal parameter, a corresponding implicitly declared subprogram with the same defining name, and having the same profile as the primitive subprogram except that T is systematically replaced by T'Class in the types of its profile, is potentially use-visible. The body of such a subprogram is as defined in {3.4.1}[12.5.1] for primitive subprograms of a [formal type when the actual type is ]class-wide{ type}.
!discussion
We would expect that the primitive equality for a class-wide type is implemented by a dispatching call on the primitive equality for the root of the class-wide type. Since 3.4.1(5) says that a class-wide type does not have primitive operations, a user-defined equality cannot be a primitive equality. So if we have a function like:
function "=" (Left, Right : T'Class) return Boolean;
This function has no effect on the semantics of membership.
This is consistent with how class-wide types are treated when used as the actual type for a formal tagged type in a generic instance -- see 12.5.1(23.1/2 - 23.2/2):
In the case where a formal type has unknown discriminants, and the actual type is a class-wide type T'Class:
* 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 as described in 3.4.1 for primitive operations of a class-wide type.
!corrigendum 3.4.1(5)
Insert after the paragraph:
The set of values for a class-wide type T'Class is the discriminated union of the set of values of each specific type in the derivation class rooted at T (the tag acts as the implicit discriminant — see 3.9). Class-wide types have no primitive subprograms of their own. However, as explained in 3.9.2, operands of a class-wide type T'Class can be used as part of a dispatching call on a primitive subprogram of the type T. The only components [(including discriminants)] of T'Class that are visible are those of T. If S is a first subtype, then S'Class is a first subtype.
the new paragraph:
When a language rule references a given primitive operation of a type, in the case of a class-wide type T'Class, this is equivalent to 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.
!corrigendum 12.5.1(23.2/2)
Replace the paragraph:
by:
!corrigendum 12.6(9.2/3)
Replace the paragraph:
For each primitive subprogram of T that is directly visible at the point of the instantiation, and that has at least one controlling formal parameter, a corresponding implicitly declared subprogram with the same defining name, and having the same profile as the primitive subprogram except that T is systematically replaced by T'Class in the types of its profile, is potentially use-visible. The body of such a subprogram is as defined in 12.5.1 for primitive subprograms of a formal type when the actual type is class-wide.
by:
For each primitive subprogram of T that is directly visible at the point of the instantiation, and that has at least one controlling formal parameter, a corresponding implicitly declared subprogram with the same defining name, and having the same profile as the primitive subprogram except that T is systematically replaced by T'Class in the types of its profile, is potentially use-visible. The body of such a subprogram is as defined in 3.4.1 for primitive subprograms of class-wide type.
!ACATS test
An ACATS C-Test is needed to ensure that the correct equality is called for a membership. It should try a case with a user-defined equality as noted above.
!appendix

From: Tucker Taft
Sent: Thursday, November 18, 2021  7:28 AM

What is the "primitive equality" for a class-wide type? This question came up
recently, regarding the wording in 4.5.2(28.1/5) describing the semantics of 
membership, where it says:


   ... If the tested type is a record type or a record extension, or is 
   limited at the point where the membership test occurs, the test uses the
   primitive equality for the type; otherwise, the test uses predefined
   equality. ...

If the tested type is a class-wide type, the wording is a bit confusing.  
Presumably the primitive equality for a class-wide type is defined by a 
dispatching call on the primitive equality for the root of the class-wide
type.  In particular, if there is a user-defined equality on the class-wide
type:

   function "=" (Left, Right : T'Class) return Boolean;

that is completely ignored.  It has no effect on the semantics of membership.

Perhaps we should define this notion of the "primitive equality of a 
class-wide type," or adjust the wording to accommodate this special case.
I could see adjusting RM 3.4.1(5) as follows:

   The set of values for a class-wide type T'Class is the discriminated union 
   of the set of values of each specific type in the derivation class rooted 
   at T (the tag acts as the implicit discriminant — see 3.9). Class-wide
   types have no primitive subprograms of their own. However, as explained in
   3.9.2, operands of a class-wide type T'Class can be used as part of a
   dispatching call on a primitive subprogram of the type T. {When a language
   rule references a given primitive operation of a type, in the case of a
   class-wide type T'Class, this is to be interpreted as a dispatching call
   on the corresponding primitive operation of T.} The only components
   [(including discriminants)] of T'Class that are visible are those of T. If
   S is a first subtype, then S'Class is a first subtype. 

This is consistent with how class-wide types are treated when used as the 
actual type for a formal tagged type in a generic instance -- see 
12.5.1(23.1/2 - 23.2/2):

   In the case where a formal type has unknown discriminants, and the actual 
   type is a class-wide type T'Class:

    * 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.

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

Questions? Ask the ACAA Technical Agent