!standard 3.2.3(6) 09-05-30 AI05-0128-1/03 !standard 6.6(6) !class binding interpretation 08-10-17 !status Amendment 201Z 09-03-09 !status WG9 Approved 09-06-12 !status ARG Approved 9-0-0 09-02-21 !status work item 08-10-17 !status received 08-08-22 !priority Low !difficulty Medium !qualifier Omission !subject "/=" is a primitive operation !summary The implicitly declared "/=" operator is primitive if "=" is explicitly declared. !question Consider: package Pack1 is type Rec is limited record F1 : Integer; end record; function "=" (Left, Right : Rec) return Boolean; end Pack1; package body Pack1 is function "=" (Left, Right : Rec) return Boolean is begin return abs(Left.F1) = abs(Right.F1); end "="; end Pack1; with Pack1; package Pack2 is procedure Proc (X, Y : Pack1.Rec); end Pack2; package body Pack2 is procedure Proc (X, Y : Pack1.Rec) is B : Boolean; use type Pack1.Rec; begin B := (X = Y); -- LEGAL B := (X /= Y); -- ILLEGAL? (No.) end Proc; end Pack2; It would be surprising if the "use type" caused "=" to become visible but not "/=". But the language rules appear to state that. USE TYPE makes primitive operators visible. 3.2.3(6) says that "=" is a primitive subprogram and therefore a primitive operator. But there is nothing in 3.2.3(2-7) that makes the implicitly declared "/=" primitive. 3.2.3(3) refers to "predefined operators", not implicitly declared operators, and it also refers to section 4.5; and 4.5.2(1) says that "=" and "/=" are predefined for nonlimited types only. Also, 6.6(6) calls the "/=" function implicitly declared, not "predefined". Since "/=" is not explicitly declared, the other bullet points in 3.2.3(4-7) don't apply. Is "/=" made visible by USE TYPE? (Yes.) !recommendation (See Summary.) !wording Add after RM 3.2.3(6): * For a specific type with an explicitly declared primitive "=" operator whose result type is Boolean, the corresponding "/=" operator (see 6.6); Modify 6.6(6): [A]{An explicit} declaration of "=" whose result type is Boolean implicitly declares {an operator}[a declaration of] "/=" that gives the complementary result. !discussion Adding a bullet to 3.2.3 seems the simplest way to include the implicitly declared "/=" operator produced when an "=" is explicitly declared. We originally considered simply eliminating the word "explicitly" from 3.2.3(6), and thereby including the implicitly declared "/=". That also would have included, redundantly, the inherited subprograms and predefined operators, but that seemed OK. The only real concern was that we might include implicitly declared subprograms that we did *not* want to consider primitive. Unfortunately, there are such cases. In particular, in the following example, an implicitly declared operation that operates on type B is not a primitive of B: package P is type A is (dummy); type B is (nothing); procedure Prim(X : A; Y : B); type C is new A; -- implicit declaration of: -- procedure Prim(X : C; Y : B); -- This is *not* a primitive of B. end P; Having clarified that "/=" is primitive, it is now obvious that it is inherited by derived types. The Ada 95 wording of 6.6(6) would imply that the implicit declaration of "=" creates a new "/=" as well, giving us two "/=" homographs with no way to choose between them (thus making calls to "/=" ambiguous). So we need to add "explicit declaration" to 6.6(6), and then clean up the wording a bit so we're not declaring a declaration (which is backwards). !corrigendum 3.2.3(6) @dinsa @xbullet, any subprograms (in addition to the enumeration literals) that are explicitly declared immediately within the same @fa and that operate on the type;> @dinst @xbullet !corrigendum 6.6(6) @drepl A declaration of "=" whose result type is Boolean implicitly declares a declaration of "/=" that gives the complementary result. @dby An explicit declaration of "=" whose result type is Boolean implicitly declares an operator "/=" that gives the complementary result. !ACATS Test An ACATS B-Test like the example in the question is needed. !appendix !topic /= is not primitive? !reference RM05 3.2.3(2-7), 4.5.2(1), 6.6(6) !from Adam Beneschan 08-10-23 !discussion In this example: package Pack1 is type Rec is limited record F1 : Integer; end record; function "=" (Left, Right : Rec) return Boolean; end Pack1; package body Pack1 is function "=" (Left, Right : Rec) return Boolean is begin return abs(Left.F1) = abs(Right.F1); end "="; end Pack1; with Pack1; package Pack2 is procedure Proc (X, Y : Pack1.Rec); end Pack2; package body Pack2 is procedure Proc (X, Y : Pack1.Rec) is B : Boolean; use type Pack1.Rec; begin B := (X = Y); -- LEGAL B := (X /= Y); -- ILLEGAL? end Proc; end Pack2; It would be surprising if the "use type" caused "=" to become visible but not "/=". But that's what I think is happening, according to the language rules. USE TYPE makes primitive operators visible. 3.2.3(6) says that "=" is a primitive subprogram and therefore a primitive operator. But I can't find a bullet point in 3.2.3(2-7) that makes the implicitly declared "/=" primitive. 3.2.3(3) refers to "predefined operators", not implicitly declared operators, and it also refers to section 4.5; and 4.5.2(1) says that "=" and "/=" are predefined for nonlimited types only. Also, 6.6(6) calls the "/=" function implicitly declared, not "predefined". Since "/=" is not explicitly declared, the other bullet points in 3.2.3(4-7) don't apply. My suggestion: Add another bullet point after 3.2.3(7): * An implicitly declared "/=", if the "=" subprogram whose declaration leads to the implicit declaration of "/=" (see 6.6) is primitive. Or something like that. **************************************************************** From: Tucker Taft Sent: Thursday, October 23, 2008 4:09 PM Are you sure you don't have too much time on your hands? ;-) Yes, I agree, it is not easy to prove that the implicitly declared "/=" is a primitive, but it definitely is if the corresponding explicitly declared "=" is primitive. Perhaps a "to be honest" in the AARM would be adequate. 6.6 might say that the "implicit" declaration of "/=" is actually considered "explicit" from the point of view of 3.2.3. We have slowly been trying to rid the language definition of rules that depend on whether a declaration is explicit or implicit, as they are almost always troublesome in some corner case like this one. ****************************************************************