Version 1.7 of ai05s/ai05-0128-1.txt

Unformatted version of ai05s/ai05-0128-1.txt version 1.7
Other versions for file ai05s/ai05-0128-1.txt

!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)
Insert after the paragraph:
the new paragraph:
!corrigendum 6.6(6)
Replace the paragraph:
A declaration of "=" whose result type is Boolean implicitly declares a declaration of "/=" that gives the complementary result.
by:
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.

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

Questions? Ask the ACAA Technical Agent