CVS difference for ais/ai-00344.txt
--- ais/ai-00344.txt 2003/08/08 01:44:10 1.1
+++ ais/ai-00344.txt 2004/03/02 04:45:00 1.2
@@ -1,5 +1,6 @@
-!standard 3.09.01 (03) 03-08-07 AI95-00344/00
+!standard 3.09.01 (03) 04-02-29 AI95-00344/01
!class amendment 03-08-07
+!status work item 04-02-29
!status received 03-04-21
!priority Medium
!difficulty Hard
@@ -7,8 +8,20 @@
!summary
+Type extensions are allowed in scopes more nested than their
+parent type. Checks are performed on function return and
+on allocators to ensure that objects of such a type extension
+do not "escape" to a less nested environment.
+
!problem
+The restriction against nested type extensions makes it harder
+to instantiate certain generics in a local scope, if those generics
+internally use extension from some kind of standard library-level type,
+such as a storage pool, or a controlled type, or a stream. Such
+restrictions can "snowball," meaning that many generics in a system may
+only permit library-level instantiations.
+
!proposal
Repeal the accessibility check in 3.9.1(3). Replace it by something that still
@@ -18,10 +31,49 @@
!wording
+Delete the last two sentences of 3.9.1(3).
+
+Add after 4.8(5):
+
+ If the designated type of the type of the allocator is tagged, the
+ accessibility level of the designated type shall not be statically deeper
+ than that of the type of the allocator.
+
+Add after 6.5(20):
+
+ If the result type is class-wide, a check is made that the accessibility
+ level of the type identified by the tag of the result is not deeper than
+ that of the master that elaborated the function body. If this check fails,
+ Program_Error is raised.
+
!example
!discussion
+[Editor's note: 3.9.1(4) is retained (which prevents extension in generic
+bodies), because the contract model issues discussed in the AARM remain.
+You can get similar issues from parameters which depend on formal types.
+See the e-mail below.]
+
+IMPLEMENTATION ISSUES
+
+When a type is extended in a more nested scope, the dispatching operations
+may need access to data declared in this nested scope. This will generally
+require a static link or global display. However, the caller of such
+a dispatching operation is generally "unaware" that they are calling
+such a nested dispatching operation. This means that the dispatching
+operation must deal with the static link or global display internally,
+using information that the caller passes in.
+
+The simplest approach seems to be as follows:
+
+When defining the record layout for a nested type extension, an
+additional implicit component is allocated to contain the static link,
+or a pointer to a saved global display, or in the case of a shared
+generic, a pointer to an instantiation descriptor in which the
+static link or global display can be found.
+
+
!corrigendum 03.09.01(03)
!ACATS test
@@ -351,5 +403,118 @@
Ultimately you end up with a whole bunch of generics
that can only be instantiated at library level.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, March 1, 2004 9:12 PM
+
+Tucker wrote in the AI: [Editor's note: Version /01.]
+
+> When defining the record layout for a nested type extension, an
+> additional implicit component is allocated to contain the static link,
+> or a pointer to a saved global display, or in the case of a shared
+> generic, a pointer to an instantiation descriptor in which the
+> static link or global display can be found.
+
+Of course, this doesn't work in the generic body for all of the reasons that
+previously been discussed.
+
+The accessibility check in generic bodies prevents all kinds of things that
+can't be implemented -- and the problems arise from issues that have nothing
+to do with accessibility. Every subprogram that can be dispatched to or
+accessed via an access-to-subprogram needs a thunk: both to add the hidden
+generic parameter (which we've talked about at length), and also to convert
+the parameter passing between the implementation for the formal and the
+implementation for the actual.
+
+If you were to put the instantiation descriptor into tagged objects that are
+extended in generic units, you could declare a wrapper that added that to
+the call for dispatching calls. And the tagged object is always passed by
+reference, so that's OK. But other parameters might have different passing,
+and you couldn't reconcile that in a wrapper (you don't know the actual
+types involved).
+
+Which brings up an interesting question: is a operation (potentially)
+primitive if it depends on a formal type? We never had to answer this in Ada
+95 for bodies; we said that it is true in specs. Consider something like:
+
+ type Root is tagged ...
+ procedure Oper (Obj : in out Root; Arg : in Natural);
+
+ generic
+ type Priv is private;
+ package Gen is
+ ...
+ end Gen;
+
+ package body Gen is
+ type New_Type is new Root with ...;
+ procedure Oper (Obj : in out New_Type; Arg : in Priv); --??
+ ...
+ end Gen;
+
+ package Inst is new Gen (Natural);
+
+Now, does Inst.Oper override the inherited one? If this occurred in the
+spec, it would. But if you do this in the body (which is currently illegal),
+then sharing without body knowledge is impossible, because you need to know
+the actual type(s) in order to determine the contents of the tag. (One also
+has to wonder about the contract model implications here.)
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, March 1, 2004 9:42 PM
+
+> Of course, this doesn't work in the generic body for all of the reasons that
+> previously been discussed.
+
+Sorry, I really don't understand your model enough
+to suggest something intelligent. In any case,
+I was presuming that the restriction 3.9.1(4) would remain:
+
+ A type extension shall not be declared in a generic body
+ if the parent type is declared outside that body.
+
+Perhaps that restriction makes no sense if we are allowing
+type extension in arbitrary non-generic bodies, but I
+presumed it was still important for shared generics
+for some reason.
+
+...
+> package body Gen is
+> type New_Type is new Root with ...;
+> procedure Oper (Obj : in out New_Type; Arg : in Priv); --??
+
+This would violate 3.9.1(4) I believe.
+
+> ...
+> end Gen;
+
+****************************************************************
+
+From: Ramdy Brukardt
+Sent: Monday, March 1, 2004 9:58 PM
+
+> A type extension shall not be declared in a generic body
+> if the parent type is declared outside that body.
+
+Sigh. I didn't remember this rule; I've always thought that the accessibilty
+check itself preventing body tagged types.
+
+Anyway, the AARM primarily discusses accessibility reasons for this rule.
+Those obviously would be gone. But it also discusses problems with abstract
+subprograms causing contract problems. Those would still remain, so we'd
+still have a reason for the rule (although we'd need to rewrite the
+explanation in order for it to make sense). I think you could construct an
+example where whether the program was legal or not depended on the actual
+type used for another parameter similar to the example I showed in my last
+message. So it looks like there are real contract problems with that, so
+there isn't a problem.
+
+But I do think a brief discussion of why 3.9.1(4) remains (and that it
+exists!) would be valuable in the AI. Otherwise, people might be expecting
+more out of this than they'll actually get.
****************************************************************
Questions? Ask the ACAA Technical Agent