CVS difference for ais/ai-00304.txt

Differences between 1.2 and version 1.3
Log of other versions for file ais/ai-00304.txt

--- ais/ai-00304.txt	2002/10/29 20:24:57	1.2
+++ ais/ai-00304.txt	2003/10/29 22:54:12	1.3
@@ -1,5 +1,8 @@
-!standard 12.5(8)                                     02-07-11  AI95-00304/00
+!standard 12.5(8)                                     03-09-30  AI95-00304/01
+!standard A.4.4
+!standard 3.2.1(3)
 !class amendment 02-07-11
+!status work item 03-09-30
 !status received 02-07-11
 !priority Low
 !difficulty Hard
@@ -7,24 +10,172 @@
 
 !summary
 
+A new category of types is proposed called "aliased" types.
+Aliased types are like tagged types in the following ways:
 
+  1) They are always passed by reference;
+  2) Formal parameters allow 'Access and 'Unchecked_Access;
+  3) User-defined "=" overrides the predefined "="
+     completely, including in a generic and in equality
+     of enclosing objects;
+  4) Formal derived types use the actual's primitives
+     rather than the ancestor's primitives;
+  5) Subtype conformance is required when overriding
+     an inherited or predefined primitive subprogram,
+     as opposed to just type conformance.
+
+The reserved word "aliased" may be used after "is"
+in a private type declaration, a formal private type
+declaration, and a composite type declaration.  If a partial
+view is aliased, then the full view must be aliased.
+All tagged types are implicitly aliased types.
+
+Individual stand-alone objects must still be explicitly
+marked "aliased" if 'Access is to be used with them.
+
 !problem
 
+There is a requirement that language-defined private
+types have "composable" equality, that is, if
+a type defined in a language-defined package is used
+as a component of another type, then equality on the
+enclosing type "works right."  The most relevant
+example is bounded strings, where equality is defined
+in terms of the characters of the abstract string represented,
+as opposed to the underlying representation, which may
+have additional padding characters which should not
+participate in the comparison.
+
+Tagged types "work right" in this context, where a user-defined
+equality operator is used in place of the predefined equality
+operator everywhere, including in generic instances and
+in equality for enclosing objects.  What is desired is
+a way to have the same "correct" semantics for user-defined
+equality, but without making the type into a tagged type,
+which has potentially undesired implications (e.g. no
+defaults for discriminants, type descriptors, implicitly
+generated stream attribute functions, support for
+Internal_Tag, etc.).
+
+Once equality operators "work right" in generics,
+it would be natural to want other user-defined
+primitives to work right for formal derived types
+(that is, the actual's rather than the ancestor's
+primitives are used in the instance).
+
+Finally, there is a generally unrelated need on occasion
+to ensure that a type is always passed by reference, and
+that 'Access or 'Unchecked_Access can be used meaningfully
+on formal parameters of the type.  Tagged types also have
+this characteristic, and hence there might be some
+value in supporting these two desires with a single
+solution.
 
 !proposal
 
+See summary.
 
 !wording
 
+TBD.
 
 !example
 
+Here is the bounded strings example:
 
+    package Ada.Strings.Bounded is
+       generic
+          Max : Positive;
+       package Generic_Bounded_Length is
+          ...
+          type Bounded_String is private;
+          ...
+       private
+          function "="(Left, Right : Bounded_String) return Boolean;
+          type Bounded_String is aliased record
+            -- "aliased" ensures no reemergence of predefined "="
+             Length : Natural range 0..Max := 0;
+             Data : String(1..Max);
+          end record;
+          ...
+
+By using "aliased" we ensure that the user-defined "="
+which presumably only compares BStr.Data(1..BStr.Length) will be
+used in all cases.  Without this, either the bounded string will
+have to be a tagged type, or Data will have to be default-initialized
+to all zeros, something which could add substantially to the
+cost of using the type if Max is relatively large.
+
+---------
+
+Here is an example of a type that is used to provide
+top-down "context" while processing a tree representation
+of a program or other modular construct.  There happens
+to be a user-defined "=" operator, and a need for the
+type to be passed by reference, with 'Access allowed on parameters.
+
+I'll admit this is a bit of a farfetched example, but
+I have certainly encountered something similar to this in
+real static analysis programs.
+
+  package Contexts is
+
+     type Context is aliased private;  -- full type must be aliased
+     type Context_Ptr is access all Context;
+
+     procedure Initialize_New_Context(Ctx : in out Context;
+       Current_Unit : Unit_Type;
+       Is_Read_Only : Boolean := False;
+       Enclosing_Context : Context_Ptr := null);
+
+     function "="(Left, Right : Context) return Boolean;
+       -- compares Current_Unit and Is_Read_Only; ignores Enclosing_Context pointer
+
+     function Is_Read_Only(Ctx : Context) return Boolean;
+     function Current_Unit(Ctx : Context) return Unit_Type;
+     function Enclosing_Context(Ctx : Context) return Context_Ptr;
+
+  private
+
+     type Context is aliased record
+         Enclosing_Context : Context_Ptr;
+         Current_Unit : Unit_Type;
+         Is_Read_Only : Boolean;
+     end record;
+
+  end Contexts;
+
+
+  with Contexts; use Contexts;
+  package body Analyzer is
+      procedure Process_Unit(Unit : Unit_Type; Cur_Context : in out Context) is
+          Local_Context : Context;
+      begin
+          Initialize_New_Context(Local_Context, Current_Unit => Unit,
+            Enclosing_Context => Cur_Context'Unchecked_Access);
+          ...
+          Process_Innards(Unit, Cur_Context => Local_Context);
+          ...
+      end Process_Unit;
+      ...
+
 !discussion
 
+We considered just making all record types "work right" but
+there were felt to be too many possibilities for subtle
+incompatibilities.
+
+One interesting side-effect of having a category of formal
+private types that is always passed by reference, and cannot
+be matched by an elementary type, is that a particularly
+simple form of generic sharing would be enabled by it.
+If the formal types of a generic were all aliased private,
+then pointers could be used for everything, and the code
+could relatively easily be constructed to be sharable.
 
 !ACATS Test
 
+ACATS tests are needed for these features.
 
 !appendix
 
@@ -193,6 +344,136 @@
 The idea that when you recompile millions of lines of legacy code that a
 warning will be sufficient help to safely change code with minimal effort
 is bogus!
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, September 30, 2003 10:22 AM
+
+In the past few weeks, there has been some
+discussion of the pain associated with reemergence
+of "=" when trying to create (untagged) private types whose
+equality "composes" properly.  The problem is that
+the predefined "=" compares all components, which
+is painful for things like bounded strings, where
+parts are potentially uninitialized.
+
+One possibility is to change the rules for (untagged)
+composite types so they match the rules for tagged types, and
+say that a user-defined "=" overrides completely
+the predefined "=", preventing it from reemerging
+in generics or in the equality for enclosing types.
+Unfortunately, this could have subtle incompatibilities
+(though I tend to believe it would fix many more
+subtle bugs than it would cause).
+
+In any case, this leads to a desire to "mark" the
+type or the "=" operator in some way to say that
+it *really* overrides the predefined operator, now
+and forever.
+
+One possibility is to have a kind of type that
+"works right" as do tagged types, but not have
+the overhead of a tag or the possibility of type
+extension.
+
+In the mean time, there has been some talk about
+having types that are always passed by reference,
+and for which 'Access is defined for formal parameters,
+which again matches the semantics of tagged types.
+
+The natural suggestion for this latter situation is
+to allow "aliased" to be used on type declarations,
+roughly in the same syntactic location as the word
+"tagged" is used, namely right after the "is" and
+before "record", "private", or "limited" (and perhaps
+also before "array".  E.g.:
+
+    type T is aliased record
+        ...
+    end record;
+
+Parameters of type T would always be passed by reference,
+and the 'Access attribute would be permitted on formal
+parameters of type T, and 'Address would always be meaningful.
+All tagged types are implicitly "aliased," so an "aliased"
+private type could be completed with a tagged full type.  Note
+that stand-alone objects would still need "aliased" if 'Access
+is to be applied to them, as is true now for "tagged."
+
+Note also that aliased private types could *not* be completed
+by elementary types (since they are passed by copy).
+That could be interesting, as it might enable a poor-man's
+generic sharing, if the formal types are all aliased private,
+the implementation can safely use pointers and pass by
+reference everywhere in the shared code body.
+
+Perhaps we can kill two birds with one stone here.
+Perhaps we can say that this new kind of type ("aliased",
+or perhaps some other term), not only has by-reference
+parameter passing and aliased formals, but also has
+rules for overriding of primitives that requires subtype
+conformance (as required for tagged), thereby allowing
+generics to always use the user-defined primitive of
+the actual type, rather than having the predefined operator,
+or ancestor primitive, reemerge in generics (and enclosing
+equality ops).
+
+Bob Duff and I used to say that "tagged types work right" when
+it comes to generics.  We could generalize this to say
+"aliased types work right."  That is, a user-defined "="
+for an aliased type would hide the predefined "=" now
+and forever.  Also, for a formal derived aliased type, the
+actual's primitive operations rather than the ancestor's
+primitives would be used in the generic instance.  Finally,
+when overriding a primitive of an aliased type, the parameter
+profile of the overriding must be subtype conformant, not just
+type conformant.
+
+Note that presuming we define all tagged types to be
+implicitly "aliased" types, then the number of rules
+in the manual can stay about the same, its just some of them are phrased
+in terms of "aliased" and "non-aliased" types rather than
+"tagged" and "untagged" types.
+
+Any comments?
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, September 30, 2003  5:22 PM
+
+This is AI-00304, assigned to one Tucker Taft. Please feel free to do your
+homework. :-)
+
+My first reaction is that the idea is OK, but seems like killing a gnat (er,
+fly) with a cannon. Detailed reactions will have to wait until after the
+meeting.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, September 30, 2003  8:16 PM
+
+Oh, thanks for the pointer.  Here is a quick draft of AI-304.
+
+[This is version /01 of the AI.]
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, September 30, 2003  8:32 PM
+
+> One interesting side-effect of having a category of formal
+> private types that is always passed by reference, and cannot
+> be matched by an elementary type, is that a particularly
+> simple form of generic sharing would be enabled by it.
+> If the formal types of a generic were all aliased private,
+> then pointers could be used for everything, and the code
+> could relatively easily be constructed to be sharable.
+
+Which of course is how Janus/Ada works for private types. If the actual type is
+pass-by-copy, we 'fake' pass by copy at the call site.
 
 ****************************************************************
 

Questions? Ask the ACAA Technical Agent