CVS difference for ai05s/ai05-0123-1.txt

Differences between 1.2 and version 1.3
Log of other versions for file ai05s/ai05-0123-1.txt

--- ai05s/ai05-0123-1.txt	2008/10/25 04:53:14	1.2
+++ ai05s/ai05-0123-1.txt	2008/12/05 04:55:35	1.3
@@ -1,4 +1,4 @@
-!standard  4.5.2(10-26)                                        08-10-18    AI05-0123-1/01
+!standard  4.5.2(10-26)                                        08-11-17    AI05-0123-1/02
 !class Amendment 08-10-17
 !status work item 08-10-17
 !status received 08-09-03
@@ -8,82 +8,80 @@
 
 !summary
 
-** TBD **
-
-!problem
-
-Consider the following example
-
-type My_Float is new Float;
-   function "=" (L, R : My_Float) return Boolean is
-   begin
-     if L > 0.99 * R and then L < 1.01 * R then
-       return True; -- Near enough
-     else
-       return False;
-     end if;
-   end "=";
-
-   type Position is
-   record
-     Latitude  : My_Float;
-     Longitude : My_Float;
-   end record;
+!summary
 
-   Position1 : Position := (90.00, 90.00);
-   Position2 : Position := (90.01, 89.99);
+Primitive "=" ops for tagged and untagged records compose alike .
 
- begin
-   if Position1 = Position2 then -  Uses original predefined equals
-                                 --  for components
+!problem
 
-The user might expect that the type Position would use the newly defined
-equality for its components. However, predefined equality reemerges unless
-the type is tagged. The user therefore has to remember to redefine equality
-for the type Position as well. This is a potential source of errors and
-confusion.
+A User-defined primitive "=" op for a tagged type "composes" in
+the sense that the predefined equality operator for an
+enclosing type which has one or more components of the given tagged
+type is defined in terms of the user-defined "=" op; the overridden
+predefined "=" op for the tagged type does not reemerge in this case.
+
+This is not true for untagged types.
+
+Tagged types were new in Ada95; thus the introduction of this rule
+in Ada95 was not an incompatible change. This rule was not introduced
+for  untagged types because that would have been an incompatible
+change.
+
+It has since been decided that, at least for untagged records,
+this was probably a mistake. Typically the feared "incompatible
+change" results in the correction of a bug.
 
 !proposal
 
-Introduce a pragma Composable_Equality(Type_Name) to indicate that the
-same composability rules that apply to tagged types also apply to the type
-Type_Name.
+If a nonlimited composite type contains a component
+of an untagged record type with a user-defined primitive
+"=" op, then the predefined equality op for the composite type
+is defined in terms of the user-defined equality op of the
+record type in the same way as if the record type were tagged.
+
+The situation is less clear for arrays because of the
+predefined lexicographic ordering operators for discrete array types
+(a change to "=" without a corresponding change to, say, "<=" seems
+like a bad idea). Thus, no analogous changes are proposed for
+array types.
+
+Tuck observes that "it would be pretty weird if the directly called
+equality didn't agree with the composed equality". For example, a
+call to the "=" operator for an untagged record type ought
+to yield the same answer aa a corresponding call to the the predefined
+"=" operator for a one-field record type whose one component is of
+the first record type.
+
+It is not clear how this principle applies in a some corner cases:
+   1) An untagged record type with a user-defined abstract
+      primitive "=" op.
+   2) An untagged record type declared in the visible part of a package
+      with a user-defined primitive "=" op declared in the private
+      part or the body of the package.
+   3) An untagged record type with a user-defined primitive "=" op
+      where the predefined "=" op is referenced before it is
+      overridden.
+
+Tuck suggests a general principle that 'you would either get a
+compile-time error, or always get the same semantics as Ada 2005
+for a direct call on "=" '.
+
+With this in mind, the preceding corner cases are all
+defined to be statically illegal.
+
+In the case of a generic formal private type where the corresponding
+actual parameter is an untagged record type with a user-defined
+primitive "=" op, reemergence does not take place. A call to the
+"=" operator associated with the formal type results in a call to
+the user-defined "=" op.
 
 !wording
 
 ** TBD **
    
 !discussion
-
-The fact that all types do not compose for equality is surprising.
-However, although it was changed for tagged types when they were introduced
-in Ada 95, it was not done for nontagged types for reasons of backward
-compatibility.
 
-One possible workaround is to declare the types to be tagged but this is
-not always appropriate.
-
-[Editor's commentary:
-It seems to me that the rationale here is poorly thought out, especially
-considering that the effects on generics are not considered. (See Pascal
-Leroy's note below for a discussion of some of them.)
-
-In any case, a solution to this problem was considered for Ada 2005
-(see AI95-00304-1). It was limited to untagged records to avoid running
-into problems with generics (like the ones noted by Pascal).
-
-For that, a pragma solution was avoided because it would violate
-Bob Duff's Rule of Good Taste in Pragmas, which is, "Pragmas should
-not have a strong effect on high-level semantics."
-
-A syntactic solution like the one proposed in that AI are annoying,
-because they're almost always what you want (and omitting it when it
-was intended would cause bad results that would be very hard to find).
-
-Eventually, this was considered just not important enough for the work
-needed (even though it was not much in the case of this proposal).
-
-I have to wonder what has changed.]
+** TBD **
 
 !example
 
@@ -1126,5 +1124,360 @@
 Right, so compilers already almost certainly have the needed circuitry.
 I know that in GNAT this would be a VERY easy change to make, probably
 a line or two.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Thursday, November 13, 2008  7:20 PM
+
+At the Portland meeting we decided to treat untagged records in the
+same way that tagged records have always been treated with respect to
+the definition of the predefined "=" operator for an enclosing composite
+type.
+
+As I remember it, we did not discuss how this is supposed to work in the
+case where the user-defined "=" op for the untagged record type is not
+visible at the point of the declaration of the enclosing composite type.
+
+Given this example,
+
+    package Pkg1 is
+       type T1 is record X, Y : Integer; end record;
+    private
+       function "=" (L, R : T1) return Boolean;
+    end Pkg;
+
+    with Pkg1;
+    package Pkg2 is
+       type T2 is record A, B : Pkg1.T1; end record;
+    end Pkg2;
+
+how should T2's equality operator behave?
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, November 13, 2008  7:41 PM
+
+For tagged types, we say that even if an overriding takes place in the private
+part, the code executed for a call on a primitive operation is independent of
+visibility. I think if we are going to try to make record equality work the
+same whether the type is tagged or not, we should probably adopt this principle
+for all record equality.
+
+In other words, so long as the "=" is overridden somewhere in the visible or
+private part of the package, it shouldn't matter whether it is visible or not.
+In short: visibility shouldn't affect composability.
+
+We should probably also adopt the "no late overriding" rule for record equality,
+disallowing overriding after the type has been frozen (and definitely not
+allowing it in a body).
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, November 13, 2008  8:30 PM
+
+That seems like adding a compatibility issue where one is not necessarily needed.
+Wouldn't it make more sense to simply say that "late" overridings don't
+participate in composition? Existing code with late equality definitions surely
+doesn't depend on composition, and breaking it solely so composition (that they
+don't use) works seems like a good way to get the idea dropped.
+
+If we were starting from scratch, you surely would be correct. Overriding would
+work very differently for untagged types (and then we wouldn't need reemergence
+in generics, either). But as it is, I'd suggest a compiler warning on late
+overriding and nothing more.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, November 13, 2008  8:51 PM
+
+I am only proposing "no late overriding" for record equality.
+I think it is important to make the late overriding illegal, to avoid confusion
+where the programmer might presume they are getting composable equality when
+they aren't.
+
+I think this is a very minor incompatibility, and it is clearly one that would be
+caught by the compiler.  If we believe that providing composability for equality
+will fix more bugs than it will introduce, we should make illegal any situation
+where you *don't* get composability when it seemed like you might.  Having a
+"half-and-half" situation seems dangerous, since there will be no easy answer
+to what user-defined equality operators are composable. That isn't doing anybody
+any favors.
+
+By the way, when I use the term "late overriding" I mean for a type declared in
+a package spec, overriding a primitive in the package body or after the type is
+frozen. That's not allowed for tagged types, but it is allowed for untagged types
+(and it's a bit of a pain to implement, by the way ;-).
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, November 13, 2008  9:33 PM
+
+> I am only proposing "no late overriding" for record equality.
+
+That's all I thought.
+
+...
+> By the way, when I use the term "late overriding" I mean for a type 
+> declared in a package spec, overriding a primitive in the package body 
+> or after the type is frozen.
+> That's not allowed for tagged types, but it is allowed for untagged 
+> types (and it's a bit of a pain to implement, by the way ;-).
+
+I could see banning it in a spec (it's easy to fix by moving the declaration
+up a few lines), but doing it in a body seems like its adding a compatibility
+problem for no reason. No sane person would expect a routine that the compiler
+doesn't even know about to participate in composibility.
+
+And the routine might depend on stuff in the body, or might really only be
+intended for local use. (I have debugging equality routines like that.) Making
+the user put it into the spec (thus making it available to the world) or making
+them rename it seems like changes that could only cause bugs (it surely isn't
+going to fix any - they're not depending on composible equality). Remember,
+the GNAT survey didn't find many instances of anyone using a potentially composed
+equality; but that doesn't mean that there isn't use of redefined equality,
+even locally only.
+
+P.S. I wouldn't consider anything that happens in the body as "overriding"
+anyway. "Overriding" is really about inheritance, and there isn't any of that
+going on in a body.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, November 13, 2008  9:51 PM
+
+> P.S. I wouldn't consider anything that happens in the body as "overriding"
+> anyway. "Overriding" is really about inheritance, and there isn't any 
+> of that going on in a body.
+
+Ahhh, but there you are wrong!  Primitives that are overridden *are* 
+inherited, even if the overriding happens very "late" (e.g. in the body).
+E.g.:
+
+    package P is
+       type T is ...  -- *not* tagged
+    end P;
+
+    package body P is
+       function "="(L, R: T) return Boolean is ... -- late overriding
+
+       type T2 is new T;
+          -- This gets the new "=".
+
+       ...
+    end P;
+
+Cool, eh?  ;-)
+
+I think this should be illegal for record equality.
+Did you imply in your earlier message that you actually do this kind of thing?
+Wouldn't you expect composability if it were legal?
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, November 13, 2008  10:42 PM
+
+> Cool, eh?  ;-)
+
+Are you suggesting a new ACATS test?? ;-)
+
+(For the record, Janus/Ada passes this test, so I suspect there already is
+such an ACATS test, probably from the Goodenough era. I've attached the full
+test below if you're as curious as I was...)
+
+> I think this should be illegal for record equality.
+> Did you imply in your earlier message that you actually do this kind 
+> of thing?  Wouldn't you expect composability if it were legal?
+
+I surely didn't derive an untagged type in a body; I consider deriving
+untagged types to be a sin just a bit below using a coextension. ;-) (The only
+reason I've done it is to "rename" the primitives of a generic easily, and I'd
+really have preferred to be able to do that without creating a new type. Dan E.
+is right on that issue.) I did declare an untagged equality in a body for
+debugging purposes (can't remember if it was named "=", though, although that
+doesn't matter too much as it surely could have been). I did it because I
+*only* wanted to debug stuff going on in that body, and I surely did not want
+it affecting anything else. If I had wanted *that*, I'd have put it in the spec
+so the world could see it! So I think your suggested new requirement would be
+actively harmful in this particular case. 
+
+I don't want to imply that this is some sort of deal-breaker, because it's
+not: user-defined record equality isn't that common, and besides, all new types
+ought to be controlled anyway. :-) I just don't see the point of worrying about
+what it does enough to want to break existing code -- I doubt there is much
+composing going on in package bodies anyway, especially of types declared
+locally.
+
+----
+
+with Ada.Text_IO;
+procedure Tuck3 is
+
+   package P is
+      type T is record -- *not* tagged
+         C : Character;
+      end record;
+   end P;
+
+   package body P is
+      function "="(L, R: T) return Boolean is  -- late overriding
+      begin
+          return True;
+      end "=";
+
+      type T2 is new T;
+         -- This gets the new "=".
+
+      Obj : T2 := (C => '1');
+   begin
+      Ada.Text_IO.Put_Line ("--- Test Tuck3 - Test late overriding"
+              & " of = for untagged types");
+      if Obj = (C => 'A') then
+          Ada.Text_IO.Put_Line ("-- OK");
+      else
+          Ada.Text_IO.Put_Line ("** Wrong = used!");
+      end if;
+   end P;
+
+begin
+   null;
+end Tuck3;
+
+****************************************************************
+
+From: Steve Baird
+Sent: Friday, November 14, 2008  2:56 PM
+
+> For tagged types, we say that even if an overriding takes place in the 
+> private part, the code executed for a call on a primitive operation is 
+> independent of visibility.
+> I think if we are going to try to make record equality work the same 
+> whether the type is tagged or not, we should probably adopt this 
+> principle for all record equality.
+
+
+At the risk of belaboring the obvious, I want to confirm that this is not
+just about composability and the equality operators of enclosing composite
+types. You are saying that a call to Pkg1."=" from outside of Pkg1 should
+execute the user-defined "=" function. Correct?
+
+I agree that this would imply that a post-freezing-point "=" declaration
+that would have been illegal for a tagged type should also be illegal for
+an untagged record type.
+
+We seem to have implicitly broadened the scope of this AI; I just want to
+make this explicit.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Friday, November 14, 2008  3:13 PM
+
+I agree, this could be perceived as broadening the AI, but it seems difficult
+to define what composability means if it is affected by visibility.  And it
+would be pretty weird if the directly called equality didn't agree with the
+composed equality.  We could avoid this problem by disallowing not only
+late overriding of record "=", but also disallowing overriding in the
+private part. That would ensure that you would either get a compile-time
+error, or always get the same semantics as Ada 2005 for a direct call on
+"=".  That might be a nice thing to be able to say.
+
+Overriding in the private part would be weird for an untagged type, and might
+imply some kind of weird intent, so it might be best to disallow it in exchange
+for getting full composability.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+I agree with your analysis.
+
+Before I attempt wording, I would like to know if there is general agreement
+that the attached !problem and !proposal sections describe where we want
+to go with this AI. [This is version /02 of this AI - Editor]
+
+****************************************************************
+
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
+
+****************************************************************
+From: Steve Baird
+Sent: Monday, November 17, 2008  7:20 PM
 
 ****************************************************************

Questions? Ask the ACAA Technical Agent