CVS difference for ais/ai-00230.txt
--- ais/ai-00230.txt 2001/10/09 00:47:09 1.6
+++ ais/ai-00230.txt 2002/02/05 02:06:24 1.7
@@ -1,4 +1,4 @@
-!standard 3.10 (01) 01-09-30 AI95-00230/02
+!standard 3.10 (01) 02-02-01 AI95-00230/03
!class amendment 00-04-13
!status work item 00-04-13
!status received 00-04-13
@@ -10,7 +10,7 @@
More general use of anonymous access types is proposed, to allow the
flexibility of implicit conversion and run-time accessibility checking to be
-used in more contexts, including as components, stand-alone variables, and as
+used in more contexts, including as components, stand-alone constants, and as
@@ -26,41 +26,105 @@
significantly reduces the need for explicit conversions when passing
references as parameters.
+With the current situation, large numbers of explicit conversions are
+required. This obscures the explicit conversions that really do
+need attention, and makes the whole OO coding style seem more cumbersome
+in Ada than in other OO languages.
Because Ada has local access types, there needs to be a way to
remember the accessibility level of the object designated by
-a reference across assignments, parameter passing, and function return.
+a reference across certain assignments, parameter passing, and
+Because Ada has multiple storage pools, it is important that an
+allocator of an anonymous access type allocate from the appropriate
The "access_definition" syntactic category (see ai-231) is permitted in more
-places than just as formal parameters and discriminants. It is permitted in
-subtype declarations, constant declarations, and for function return types. The
-type associated with the subtype, constant, or function return is an anonymous
-access type, which permits implicit conversions from other access types with
-appropriately compatible designated subtypes (as defined by 4.6(13-17)).
+places than just as formal parameters and discriminants. In addition to the
+current places (IN parameters and discriminants of limited types) it would
+be permitted in stand-alone constant declarations, formal IN objects,
+component definitions, for function return types, and for discriminants of
+non-limited types. The type associated with constant, formal IN, component,
+or function return is an anonymous access type, which permits implicit
+conversions from other access types with appropriately compatible designated
+subtypes (as defined by 4.6(13-17)).
The accessibility level of an anonymous access type is determined at the time
when the access_definition is elaborated. For a function return type, this
-happens at the time the function returns.
+happens at the time of the function return.
-For a subtype of an anonymous access type, the accessibility level is the level
-of the subtype declaration. For a constant declaration, the level is the same
-as the level of the type of the initial value. For a function return, the
-level is the same as the level of the type of the returned value, which must be
-shallower than the level of the execution of the function (for obvious
+The general accessibility level rule is that for an access value which
+cannot be altered during its lifetime (in parameter, stand-alone constant,
+IN object, discriminant of a limited type, function return value), its level
+may be determined by the accessibility level of its initial value or
+enclosing object. For others (i.e. other kinds of components)
+the accessibility level must be determined by the level of its
+declaration. This is necessary to simplify implementation and to
+avoid dangling references when an access object is updated while
+being "viewed" at a deeper level than it truly is (which is always
+permitted by the current accessibility checking rules).
+[NOTE: We considered allowing anonymous access types in stand-alone
+variable declarations. However the above general rule would force them
+to have a level determined by their declaration rather than initial value.
+This might create confusion when copying an access parameter into a local
+variable and unintentionally losing the accessibility level information.
+By only allowing constants, and having them preserve the accessibility level
+information, we avoid this possible problem.]
+Applying this general rule to the specific cases means that
+for a constant declaration/formal IN object, the level is the same as the
+level of the type of the initial value. For a component definition, or a
+discriminant of a nonlimited type, the level is the same as that of the
+enclosing composite type. As in the current language, IN parameters take
+their level from the initial value, and discriminants of limited types
+take their level from the enclosing composite *object* (as opposed
+to enclosing type).
+For a function return, the level is the same as the level of the type
+of the returned value, which must be shallower than the level of the
+execution of the function (to avoid dangling references by the caller).
+If the return expression is an allocator, the accessibility
+level and storage pool for the allocator is determined by the context
+of the call on the function. This implies that the call on
+a function with an anonymous access return type must be passed
+in a storage pool and an accessibility level, and must return
+both an access value and an accessibility level. [Implementation NOTE:
+The implementation may implement the accessibility level check either
+after returning from the call, or at the point of the return statement, since
+it has enough information to do it there as well.]
There is a special predefined equality (and matching inequality) operator
declared in package Standard which requires at least one of the parameters to
be of an anonymous access type, and the other to be convertible to that
anonymous access type.
-An anonymous access type uses the default storage pool associated with its
-accessibility level. If an anonymous access type is used as the parent in a
-derived type declaration, the derived type is a "normal" access type, without
-any implicit conversion from other access types. An anonymous access type may
-be passed to a generic when the formal is an access type or a private type.
+The storage pool to be used for an allocator of an anonymous access type
+is determined by the context in which it appears:
+a) As the value for an IN parameter, constant, or formal IN object of an
+ anonymous access type, an anonymous storage pool whose storage is
+ reclaimed when the function returns, or at the end of the constant's
+ or formal IN object's scope;
+b) As the initial value for a discriminant of a limited type, the same
+ storage pool as used for the enclosing object, if it is created by
+ an allocator, or an anonymous storage pool whose storage is
+ reclaimed when the enclosing object's scope ends.
+c) As the initial value for a component other than a discriminant of
+ a limited type, a standard storage pool similar to that which would be used
+ for a named access type declared at the same level as the enclosing composite
+d) As a return expression for a function whose return type is anonymous,
+ the same storage pool that would be used had the allocator appeared
+ at the point of the function call. (This rule is applied recursively
+ for a chain of calls.)
@@ -109,54 +173,66 @@
seem unnatural to require the use of tagged and class-wide types just to get
the implicit conversion on named general access types that is already available
for all anonymous general access types.
+We have decided to disallow named subtypes of anonymous access types, because
+they seemed to create more problems than they solved.
-We have proposed to allow named subtypes of anonymous access types, which is
-admittedly a mind-bending concept. However, subtypes have exactly the right
-implicit convertibility semantics, which is not in general shared by types. So
-by using subtype declarations to introduce these, hopefully we are suggesting
-the implicit convertibility. [Note that a recent suggestion regarding the
-"incomplete type stub" is to actually call these "subtype stubs" for a similar
-In addition to allowing access_definitions in subtype declarations, we have
-also proposed to allow them in constant declarations and function returns. We
-considered broadening this to more contexts, but this began to require that
-accessibility was associated with individual values rather than types. That
-would be a pretty big change to the accessibility level model, and bigger than
-seemed necessary. In both of these contexts, we can define the elaboration of
-the access_definition construct to occur at the time when the one and only
-value is provided, and thereby carry the accessibliity level of the
-initializing value's type into the accessibliity level of the anonymous type.
-If we allowed access_definitions in variable declarations or updatable
-component declarations, we would have difficulty specifying the accessibliity
-level of the anonymous type. Furthermore, we would need to define how run-time
-accessibliity level is carried across assignments.
-By allowing named subtypes of anonymous access types, we effectively allow
-the declaration in any context of objects which support implicit conversion,
-including as stand-alone variables and record or array components.
-However, because the accessibliity level of a named subtype is determined by
-the level of the subtype declaration containing the access_definition, objects
-of these named subtypes do not require any run-time accessibility checking.
-We have allowed anonymous access types to be used in derived type declarations
-and generic instantiations, but they effectively lose their implicit
-convertibility at that point. We considered disallowing them, but could find
-no compelling reason to do so, and the usual generic contract model problems
-associated with going down that slippery slope. Similarly, we considered
-disallowing allocators for anonymous access types, but since they are already
-allowed for access parameters and access discriminants, there seemed no good
-reason to disallow them for these new contexts.
+We have proposed to allow anonymous access types in constant declarations,
+formal IN objects, component definitions, and function returns. We considered
+broadening this to include stand-alone variable declarations, and variables
+declared as [IN] OUT parameters or IN OUT formal objects, but that created
+the possibility of confusion about whether accessibility level information
+is lost when copying an access parameter to a local variable. Alternatively,
+the variable could retain the accessibility level information, but then
+we would have to carry run-time accessibility levels across assignment
+statements with an accompanying accessibility check as well to handle
+up-level assignments. Furthermore, this would totally change the model,
+since thus far, we have fully determined the accessibility level
+at the point of the elaboration of the anonymous access type.
+We handle updatable components by specifying that their accessibility
+level is determined by the enclosing composite type. This provides
+the advantages of implicit conversion, without needing run-time
+accessibility levels for individual components.
-Allowing constant declarations and function return types to use
-access_definitions is not critical to this proposal, and could be dropped.
Constant declarations with access_definitions are no harder to support than
-access parameters (ditto goes for formal IN objects, I suppose). Function
-returns is harder to support, but also opens up new possibilities for creating
-functions which can return references to aliased components of objects that are
-themselves passed in using an access parameter. This would effectively allow
-functions that act as "selectors" that can be used on the left hand side of an
-assignment when followed by ".all". E.g:
+access parameters (ditto goes for formal IN objects).
+Component declarations with access_definitions have no special accessibility
+level issues, because the level is determined just like a named access
+Function returns are harder to support, but also provide important
+capabilities that are currently very difficult to accomplish.
+First of all, one can define a function that constructs an object
+(including an object of a limited type) in a storage pool determined
+by the caller, including a "stackish" storage pool (i.e. one that
+is cheap to reclaim). This kind of constructor is definitely
+missing in Ada now. Currently, the access type, and hence the
+storage pool, must be known inside the function that creates
+an object. Secondly, there is no way to create a single function
+that can be used both for creating a local object and a heap object
+with similar efficiencies. With this proposal, the "constructor"
+would look like this:
+ function Construct(...) return access T is
+ return new T'(...);
+ X : constant access T := Construct(...); -- Create on the stack
+ Y : constant T_Ptr := Construct(...); -- Create in T_Ptr'Storage_Pool
+Secondly, one could define a function that could return a reference to
+an aliased component of an object that is itself passed in using an access
+parameter. This would effectively allow a function to act as a "selector"
+that can be used on the left hand side of an assignment when followed by
X : aliased Rec_With_Aliased_Component;
@@ -1656,6 +1732,22 @@
I've tried to raise the "in out" issue at the ARG meetings without success.
People are afraid that the same old bunch of opponents (minus at least one --
me!) would resurface.
+From: Tucker Taft
+Sent: Friday, February 1, 2002 11:54 AM
+Here is an update to ai-00230 on anonymous access types.
+I was able to resolve the problems that I had with them last time,
+while eliminating the mind-bending named subtypes of anonymous access types,
+but adding back components of an anonymous access type.
+I think it all works safely and usefully now, especially presuming
+the syntax for "access_definition" is generalized (see ai-231) to allow
+control over nullness, and constantness of the designated object.
+[See AI body for current proposal - Ed.]
Questions? Ask the ACAA Technical Agent