!standard A.18.2(87/2) 21-06-07 AI12-0434-1/03 !standard A.18.3(59/2) !standard A.18.4(18/2) !standard A.18.7(17/2) !standard A.18.10(76/3) !class binding interpretation 21-05-28 !status Amendment 1-2012 21-06-07 !status WG9 Approved 22-06-22 !status ARG Approved 14-0-0 21-06-03 !status work item 21-05-28 !status received 21-05-28 !priority Low !difficulty Easy !qualifier Clarification !subject Equality operators for container cursors !summary The equality operator for a container cursor, like any other operator in a language-defined package, can be user defined. !question A.18.4 (18/2) says: The predefined "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container. Can this operation be user-defined? (Yes.) !recommendation (See Summary.) !wording Modify A.18.4 (18/2): The {primitive}[predefined] "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container. {AARM To Be Honest: "The primitive "=" operator" is the one with two parameters of type Cursor which returns Boolean. We're not talking about some other (hidden) primitive function named "=".} Change A.18.2 (87/2), A.18.3 (59/2), A.18.7 (17/2), and A.18.10 (76/3) in the same way. !discussion The author believes that this is much ado about nothing. Nothing in the RM says that this operator has to be predefined. The use of "predefined" here is just identifying the operator being discussed. As-if implementations of language-defined packages are always allowed; in particular, any operator can be user-defined so long as that definition meets the requirements of the language (such as composition) and the redefinition does not change the semantics as visible to the user (so one has to be careful with parameter names and subtypes). No language-defined package would be implementable without such an interpretation - one always needs to add semantic dependencies for helper packages to implement the private parts of language-defined packages. Taken literally, this interpretation would mean that no implementer could use a user-defined operator in a language-defined package unless that operator is explicitly defined in the specification of the package. That would mean that heroic efforts (such as building almost all language-defined packages into the compiler) would be needed for many Ada types. For instance, only predefined "=" could be used for type Controlled, meaning a special-case implementation would be needed for such equality. Since the "=" operator for cursors is not explicitly present in the specification, "predefined" was used to identify the operator whose behavior was being specified. We still need some phrase to do that, as we are not intending to put any requirements on "=" other than the usual one. Note that 4.5.2(32.1/1) requires composition of equality of this and all other private types in language-defined packages, and AARM A.18(5.q/2) specifically calls out composition as required for the containers and cursors. There's no need to mention that further. --- We considered other possible changes here: (1) Define an "=" operator for cursors in the specification of all of the container packages. Then the word "predefined" is not needed in the paragraph above. This was rejected as it makes the operator user-defined even when that is not necessary. (2) Use the description of the "usual" equality as defined in 4.5.2(9.8/5): "the primitive equality operator that is type conformant with that of the corresponding predefined equality operator" Surprisingly, this was considered too wordy. :-) (3) Leave it as it is, and add an AARM To Be Honest note (or perhaps Implementation Note) telling any implementer that the use of "predefined" in this paragraph simply identifies the operator being specified, and has no effect on how it could be implemented. This was rejected as being misleading. !corrigendum A.18.2(87/2) @drepl The predefined "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container. @dby The primitive "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container. !corrigendum A.18.3(59/2) @drepl The predefined "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container. @dby The primitive "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container. !corrigendum A.18.4(18/2) @drepl The predefined "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container. @dby The primitive "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container. !corrigendum A.18.7(17/2) @drepl The predefined "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container. @dby The primitive "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container. !corrigendum A.18.10(76/3) @drepl The predefined "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container. @dby The primitive "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container. !ASIS No ASIS effect. !ACATS test No ACATS test needed. !appendix From WG 9 Review Issue #144. A.18.4 (18/2) says: The predefined "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container. In fact, it is fine if there is a user-defined "=" operator for type Cursor, so long as it composes properly. Hence, I would suggest we drop the "predefined" and either add an AARM note or an Implementation Requirement that this "=" operator composes properly. Same problem occurs in A.18.2 (87/2), A.18.3 (59/2), A.18.7 (17/2), and A.18.10 (76/3) All five of these can be found by searching the RM for the exact phrase "if both cursors" [Reply from Randy Brukardt:] 4.5.2(32.1/1) clearly applies to type Cursor (it is a nonlimited type declared in a language-defined package), so I don't think anything normative about composition is required (it is required of equality of all language-defined types). I won't even bother with an AARM note, since we discuss the fact that language blanket rules apply to containers in the introduction (AARM A.18(5.q/2) specifically calls out composition). I personally think this request is overly pedantic; from the perspective of a user of a package, whether an operator is predefined or user-defined is irrelevant - whether something is privately overridden is neither visible nor matters. I'd guess that there are quite a few similar wordings throughout the RM. Moreover, this wording has been present since Ada 2005, and there's no evidence that anyone was confused. Anyway, I'm rather close to clicking on the deferred label, but I'll leave this unmarked for now, if there is time before next Friday, I'll deal with it. [Reply from Tucker Taft:] This is not actually just "pedantic" since attempts to ensure that the "predefined" equality had the right properties significantly complicated the implementation, and led to some bugs. Once we concluded that all that mattered was that the equality operator composed, we were able to simplify things and avoid various bugs. So I believe we should at a minimum remove "predefined" from the normative wording. Whether we should also add an AARM note somewhere is a separate issue, and I leave that in the Editor's hands... [Reply from Randy Brukardt:] I disagree - "as if" changes to language-defined packages are always allowed, and certainly redefining an operator falls into that category. If that wasn't true, pretty much the entire set of Ada predefined units would require heroic efforts to implement. Your always allowed to add things (declarations, context clauses, etc) that don't change the user semantics of a unit. Nothing given in English text changes that fact, so such a concern is pedantic at best. I think there are dozens of similar cases in the RM, and I don't see any reason to prioritize this one over any others (other than that someone is complaining). Still, the absolute lowest priority to fix for me. [Reply from the editor:] I've made a mostly empty AI (AI12-0434-1) for this topic. I don't believe that just dropping "predefined" works, as there is no equality visible in the specification and it is unclear what is being talked about in this case (there could be other equalities that are user-defined or hidden from users). I suppose we could say "primitive" equality here, similar to the rules in 4.5.2, which refers to the equality that is used for composition. ****************************************************************