CVS difference for 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