Version 1.5 of 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:
- 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.
by:
- 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.
!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