!standard 3.4.1(5) 22-01-24 AI22-0027-1/01 !standard 4.5.2(28.1/5) !class binding interpretation 22-01-24 !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. !question 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 Modify 3.4.1(5): 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. !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. Note that this 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. !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. ****************************************************************