AI22-0163-1
!standard 3.10.2(2.2/2) 26-06-28 AI22-0163-1/02
!class Amendment 26-06-06
!status work item 26-06-06
!status received 26-06-06
!assigned author Brad Moore
!submitter Brad Moore
!priority Medium
!difficulty Medium
!subject Allowing ‘Access to return a universal_access value
Allow ‘Access (and ‘Unchecked_Access) attribute references to generate a universal access value. Such a capability could facilitate writing improved pre and post condition contract specifications for storage subpools, for example.
For the standard storage subpools package in 13.11.4, the Allocate_From_Subpool and Deallocate_Subpool primitives specify preconditions of the form:
with Pre'Class => Pool_of_Subpool(Subpool) = Pool'Access
This currently isn’t legal because the “=” operation being applied here is comparing values of an anonymous access type, which uses the operator of the universal access type, and the requirements for the ‘Access attribute in 3.10.2(2/2, 2.1/2) do not allow for it to be used in such a context.
These rules state:
For an attribute_reference with attribute_designator Access (or Unchecked_Access — see 13.10), the expected type shall be a single access type A such that:
It is hard to see how universal access would meet these requirements.
There are ways to work around this in Ada to achieve similar effects for these preconditions, such as adding helper functions to do the checking, but it would be cleaner and easier to read to write these as currently specified in the standard, without adding extra clutter to the specification of such packages.
We recommend that the rules for ‘Access (and ‘Unchecked_Access) be relaxed to specifically allow universal access as the expected type for ‘Access.
Modify 3.10.2(2.2/2):
Allowing the universal_access type to be the expected type of an Access attribute reference would allow the existing preconditions for the Storage subpool’s Allocate_From_Subpool and Deallocate_Subpool primitives to be legal. Since this is a relaxation of the rules, we need to consider if there might be unwanted side effects for allowing this change, from a dynamic semantics point of view.
On the surface, it seems that such effects are not likely if you consider the following:
We could simply modify the preconditions of the Subpools child package of Storage_Pools to make them legal without making this change, by adding a Pool_Access helper function.
function Pool_Access
(Pool : in out Root_Storage_Pool_With_Subpools)
return access Root_Storage_Pool_With_Subpools'Class is
(Pool'Unchecked_Access);
procedure Allocate_From_Subpool
(Pool : in out Root_Storage_Pool_With_Subpools;
Storage_Address : out Address;
Size_In_Storage_Elements : in Storage_Elements.Storage_Count;
Alignment : in Storage_Elements.Storage_Count;
Subpool : in not null Subpool_Handle) is abstract
with Pre'Class => Pool_of_Subpool (Subpool) = Pool_Access
(Pool),
Global => overriding in out Subpool;
procedure Deallocate_Subpool
(Pool : in out Root_Storage_Pool_With_Subpools;
Subpool : in out Subpool_Handle) is abstract
with Pre'Class => Pool_of_Subpool (Subpool) = Pool_Access (Pool);
The Pool_Access function returns the Universal_Access type value that is used in the “=” comparison, much like the ‘Access attribute reference would, if it were allowed. We would need to use ‘Unchecked_Access in the Pool_Access function only because there is a legality rule that disallows using ‘Access on a local variable (the Pool formal parameter). If we could replace the Pool_Access function with the ‘Access attribute reference, this shouldn’t be an issue since the attribute reference result would only be used locally.
While adding a Pool_Access function to the Subpools package specification could resolve this issue, it would add clutter to the specification that wouldn’t be needed if ‘Access could be used instead.
On the other hand, if the need for this feature is uncommonly rare, it could be considered overkill to modify the language’s resolution rules to provide this functionality. This is especially the case when the availability of a relatively simple workaround is possible, as shown above, without having to modify name resolution rules. We may want to survey existing code bases to see if there are other places where such a feature would be nice to have. A point to consider is that other proposed new features, optional components, for example, may further reduce the need for such a feature, as there could be less need to use explicit access type comparisons.
We should consider whether there are any other dynamic semantic issues of concern, but none are known at this time.
See the standard Subpools package specification in 13.11.4.
ACATS B-Tests should check that the results of ‘Access and ‘Unchecked_Access attribute references can be used in comparisons against universal access type values for equality.
Similarly, ACATS B-Tests should test these attribute results in /= comparisons.
ACATS C-Tests should also test if renaming declarations for expressions that make use of ‘Access and ‘Unchecked_Access work as expected.
See ARG GitHub issue #173 for some discussion of this issue.
[a]This doesn't work as written, as the type of prefix of the attribute is required to be the designated type of the access type (that is, type D). But universal access does not define any designated type. Moreover, all of the rules that define the Access attribute (paragraphs 23-32) depend on there being a defined designated type or profile.
I suppose you could redo the resolution for universal equality operators to propagate the designated type from the "specific anonymous access type" in such a case, but that would only expand the mess.
[b]It seems to me that making major changes in resolution and legality rules simply to fix a single precondition is overkill, especially as the feature in question should be used less often in future code (assuming that optional components get adopted).
[c]Duuno if there are other use cases. My point about optional components is simply that there should be a lot fewer access types in future programs, and if that is the case, there should be a lot fewer 'Access uses as well.
BTW, Google Docs has somehow lost many of the comments on this AI and on AI22-0162, you can see them in the comments pane but not when viewing or exporting the documents. Try to handle all of them (like my complaint about testing).
[d]You said above that this doesn't work as written because the type of prefix of the attribute is required to be the designated type of the access type (that is, type D), but that only applies to the bullet 3.10.2(2.1/2). But there are "or"s between the three bullets (including the proposed new one), so it seems to me, this should be OK on that point.
[e]The Legality Rules for the access attribute are defined in 3.10.2(24-32). Some of those rules depend on the designated type of the expected type, which is named 'D' by 3.10.2(24/1), specifically 3.10.2(27-27.2). How do those rules get enforced if there is no D??? One could write some special rules for universal access, I guess, but that would likely allow some conversions not otherwise allowed (which sounds dangerous). Doing nothing certainly does not work.
[f]Seems like we should leave this one as is, rather than spend more time creating a bigger mess, as you say, and get some consensus from the group to see if there is enough motivation to push forward with a solution on this, or fall back on the simple solution shown earlier in this AI, which would be fairly trivial by comparison.