Version 1.5 of 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 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); --
B := (X /= Y); --
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;
--
--
--
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:
- For a specific type declared immediately within a package_specification,
any subprograms (in addition to the enumeration literals) that are explicitly declared
immediately within the same package_specification and that operate on the type;
the new paragraph:
- For a specific type with an explicitly declared primitive "="
operator whose result type is Boolean, the corresponding "/=" operator
(see 6.6);
!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