CVS difference for ais/ai-00391.txt

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

--- ais/ai-00391.txt	2004/11/14 04:55:05	1.1
+++ ais/ai-00391.txt	2004/11/17 00:52:59	1.2
@@ -142,4 +142,280 @@
 
 !appendix
 
+From: Dan Eilers
+Sent: Monday, November 15, 2004  1:54 PM
+
+> There are various possible solutions.  One would be a kind
+> of "type rename" clause which would implicitly declare renames
+> of all of the primitive subprograms of the type as well.
+
+I'd like to expound a bit on this "type rename" idea, since it
+solves a broader class of problems, and is therefore a potentially
+viable idea whether or not Tuck's proposed solution is implemented.
+
+Derived types are intended to serve two purposes:  1) the Ada83 purpose
+of creating two distinct types (e.g., apples and oranges) that are
+incompatible although they have common representation and operations;
+and 2) the Ada95 purpose of type extension.
+
+However, derived types are commonly abused to serve the purpose
+of making a type declaration accessible outside the package in
+which it is declared.  This purpose was supposed to be served
+by type renaming, as stated in Steelman requirement 3-5B:
+"Definitions that are made within an encapsulation and are externally
+accessible may be renamed before use outside the encapsulation."
+
+Apparently, type renaming was omitted from Ada as an economy measure,
+under the delusion that the same effect could be achieved via a
+constraint-less subtype declaration, as is claimed in RM 8.5(6).
+This claim is not completely true, since subtype declarations cannot
+be used to complete a private type declaration.
+
+The need for type renaming to provide the completion for a
+private type declaration stems from another unmet Steelman
+requirement, generic types, as stated in Steelman requirement 12D:
+"12D. Generic Definitions. Functions, procedures, types, and
+encapsulations may have generic parameters."
+
+If generic types were available (or class-like packages that
+exported a type), a private type could often be completed directly
+as the instantiation of a generic type (or class, resp), with no
+need for either type derivation or type renaming.  Instead, the user
+must enclose such a type in a generic package and instantiate that
+package, creating the need to somehow reach into the instantiated
+package when completing the private type.
+
+For example, we would like to say:
+
+  with sets;
+  package p1 is
+     type int_set is private;
+  private
+     type int_set is new sets(integer);  -- illegal, no generic types
+  end p1;
+
+Instead we say:
+
+  with sets;
+  package p2 is
+     type int_set is private;
+  private
+     package int_sets_pkg is new sets(integer);
+     -- subtype int_set is int_sets_pkg.set;    -- illegal use of subtype
+     -- type int_set renames int_sets_pkg.set;  -- illegal, no type renaming
+     type int_set is new int_sets_pkg.set;      -- OK, but abuse of derivation
+  end p2;
+
+This use of derivation to achieve type renaming is an abuse because
+the user doesn't want two distinct types, int_set and int_sets_pkg.set.
+Instead, the user wants int_set to be the same type as int_sets_pkg.set,
+just with a different name and scope.  A reader/maintainer is forced to
+consider whether two distinct types are being created on purpose, or
+only as an unwanted side effect.
+
+The users also wants the type renaming to create renames of the primitive
+operations, so these operations are also visible in the scope of int_set.
+This is analogous to the way derived types work, only simpler, since
+there is no need for implicit conversions of operands and/or result types.
+
+As Tuck explains, this abuse of derivation causes a further complication
+when the type has one or more functions with controlling results, because
+such functions must additionally be overriden, even if they are never used.
+
+Fixing this need to overide such functions would make derived types
+somewhat somewhat more palatable as a substitute for type renaming, but
+it would still be an abuse.
+
+Adding type renaming would satisfy the original Steelman requirement 3-5B.
+It would improve understanding of the language, eliminating the silly
+restriction that other definitions can be renamed, just not types.
+The use of renaming for type completion would be directly analogous
+to the use of renaming-as-body for subprogram completion, and therefore
+easy to understand.  Type renaming used for completing private types
+would improve the readability of programs, since it prevents creation
+of an unwanted incompatible type.
+
 ****************************************************************
+
+From: Tucker Taft
+Sent: Monday, November 15, 2004  3:17 PM
+
+I think type renames are interesting, but too big a change
+at this point.  I am also made very nervous by a private
+type completed by a type rename, since you now have two
+distinct scopes where you could define primitives of
+the type, one where the type was originally defined, and
+one where it was renamed.  I had imagined a type rename
+more like a combination of a subtype declaration and a
+set of renames of the primitive subprograms.  That would
+solve the problem of making the type and its primitives
+visible, but it wouldn't allow you to complete a private
+type, nor add more primitives at the point of the renaming.
+
+I don't know how you weight the advantages of making the
+type and its primitives visible versus the ability to
+complete a private type.  I don't see much alternative
+to the type derivation model if you are completing a
+private type, because of the possibility of adding more
+primitives.  Since the type derivation model has been
+in use for the past 20 years, it seems hard to justify
+introducing a feature with so much overlapping functionality
+at this time.  In any case, as I said above, this seems way too
+much for a last minute "quick fix."
+
+****************************************************************
+
+From: Dan Eilers
+Sent: Monday, November 15, 2004  8:15 PM
+
+>                 I am also made very nervous by a private
+> type completed by a type rename, since you now have two
+> distinct scopes where you could define primitives of
+> the type, one where the type was originally defined, and
+> one where it was renamed.
+
+Yes, this makes me nervous too, now that you point it out.
+But in the case I'm trying to get to work (where a private type
+is completed by renaming a type created by an instantiation),
+the user doesn't intend to ever again reference the type
+created by the instantiation.  So there may be a solution
+if this can be enforced.
+
+Here's a new proposal:
+
+Instead of the current way of:
+     package int_sets_pkg is new sets(integer);
+     type int_set is new int_sets_pkg.set;
+
+or my proposed way of:
+
+     package int_sets_pkg is new sets(integer);
+     type int_set renames int_sets_pkg.set;
+
+do something like:
+
+     type int_set is new sets(integer).set;
+
+where sets(integer) is an anonymous instantiation.
+Since the instantiation is anonymous, there is no
+possibility of the user ever subsequently referencing
+the instantiation or types within it.
+
+> I don't know how you weight the advantages of making the
+> type and its primitives visible versus the ability to
+> complete a private type.
+
+I'm most concerned with completing a private type without
+out needing derived types, preferably in a way that
+resembles instantiation of generic types/classes.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, November 15, 2004  8:39 PM
+
+The idea of anonymous instantiations was floated during
+the Ada 9X process, with something pretty close to
+the syntax Dan proposes.  We didn't pursue it, but
+I don't know all the reasons.  I do know it seems
+like a lot of work just to avoid using a type
+derivation.  And I think behind the scenes the
+implementor would have to do a type derivation to
+avoid a huge implementation effort.  I can also
+imagine that handling anonymous instantiations
+might involve some pain in the debugger, etc.,
+dealing with stepping through anonymous instantiations,
+coming up with unique link names, etc.
+
+Based on the C++ experience, anonymous instantiations
+are generally a pain, and the gain comes primarily from
+*implicit* instantiations for generic subprograms,
+something which is a very big language design
+problem, and I suspect also a big implementation
+problem.
+
+Now if we were talking about adding *iterators* I
+know a few ARG members who might get excited, but
+anonymous instantiations doesn't do it, at least
+not for me.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, November 15, 2004  7:21 PM
+
+I'm working on the Abstract Types section today, and one of the AARM notes
+caused me to think a bit about Tucker's proposal. As written, it allows the
+creation of objects of an abstract type, which is a no-no.  Consider:
+
+  package P1 is
+    type Something is tagged record ...;
+    function Constructor return Something;
+    type Acc_All is access all Something'Class;
+  end P1;
+
+  with P1;
+  package P2 is
+    type Tucker_Type is abstract new P1.Something with null record;
+    -- Illegal in Ada 95, legal and inherits a concrete function Constructor
+    -- with Tucker's proposal.
+    Ptr : P1.Acc_All := new Tucker_Type'Class (Tucker_Type'(Constructor));
+       -- Now we have an object of an abstract type, with the tag of the
+       -- abstract type.
+  end P2;
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Monday, November 15, 2004  7:21 PM
+
+Hmm.  I think (I'm leaving out irrelevant words) "the type of an object
+created by an allocator shall not be abstract" at 3.9.3(8) saves us
+here.  I.e. the above is still illegal, as it should be.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, November 15, 2004  7:45 PM
+
+I don't think that applies: class-wide types are never abstract, and that's
+the type of the object that we're creating. Even if it does apply, but there
+are other ways to make such a call. Try:
+
+    procedure Ugh (Obj : in Tucker_Type'Class);
+
+    Ugh (Constructor); -- Tag-indeterminant call.
+
+Ugh could have the allocator, and there'd be no way for a legality rule to
+check it there!
+
+The problem is having a concrete function returning an abstract object. Once
+you have that, there's always a way to get that into an object. Clearly,
+Tucker's AI will need to avoid including them in his "null extension"
+definition.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, November 15, 2004  8:18 PM
+
+Bob's comment may save us, but it would be simpler
+to just fix the suggested wording of the AI to say:
+
+Modify 3.9.3(4) of AI-251:
+
+    If a type inherits a subprogram corresponding to an abstract
+    subprogram{, or a type other than a NONABSTRACT null extension
+    inherits} [or to] a function with a controlling result, then:
+
+Modify 3.9.3(4):
+
+    * Otherwise, the subprogram shall be overridden with a nonabstract
+      subprogram {or, in the case of a private extension inheriting
+      a NONABSTRACT function with a controlling result, have a full type
+      that is a null extension}; ...
+
+The added word here is "NONABSTRACT" in both sentences.
+
+****************************************************************
+

Questions? Ask the ACAA Technical Agent