AI22-0082-1
!standard A.18.2(34.1/5) 24-04-24 AI22-0082-1/04
!standard A.18.2(34.2/5)
!standard A.18.2(79.10/5)
!standard A.18.2(79.11/5)
!standard A.18.2(147.1/5)
!standard A.18.2(147.2/5)
!standard A.18.3(17.1/5)
!standard A.18.3(17.2/5)
!standard A.18.3(51.10/5)
!standard A.18.3(51.11/5)
!standard A.18.3(86.1/5)
!standard A.18.3(86.2/5)
!standard A.18.4(41.1/5)
!standard A.18.4(41.2/5)
!standard A.18.5(17.1/5)
!standard A.18.5(17.2/5)
!standard A.18.5(37.11/5)
!standard A.18.5(37.12/5)
!standard A.18.6(16.1/5)
!standard A.18.6(16.2/5)
!standard A.18.6(51.12/5)
!standard A.18.6(51.13/5)
!standard A.18.7(36.3/5)
!standard A.18.7(96.1/5)
!standard A.18.8(17.2/5)
!standard A.18.8(58.1/5)
!standard A.18.8(59.10/5)
!standard A.18.9(16.2/5)
!standard A.18.9(73.1/5)
!standard A.18.9(74.10/5)
!standard A.18.10(28/5)
!standard A.18.10(29/5)
!standard A.18.10(70.10/5)
!standard A.18.10(70.11/5)
!standard A.18.10(122/5)
!standard A.18.10(123/5)
!standard A.18.18(16/5)
!standard A.18.18(17/5)
!standard A.18.18(52/5)
!standard A.18.18(53/5)
!class Binding Interpretation 23-09-26
!status Corrigendum 1-2022 23-12-14
!status WG9 Approved 24-06-10
!status ARG Approved 11-0-1 23-12-14
!status work item 23-09-26
!status received 23-09-26
!submitter Stephen Baird
!priority Medium
!difficulty Medium
!qualifier Error
!subject Problems with nonlimited reference types
Nonlimited reference types cause problematic ambiguities. These types are eliminated from language-defined packages.
A name that denotes an object of a reference type may be interpreted in either of two ways: it may be interpreted in the "usual" way (that is, as a name denoting the given object) or it may be interpreted as a generalized_reference (i.e., as a name denoting the object designated by
the reference discriminant of the given object).
It is well understood and uncontroversial (albeit still sometimes annoying) that this can result in (illegal) ambiguities in some cases.
In this example,
type Int_Ref (Ref : access Integer) is null
record
with Implicit_Dereference => Ref;
Int : aliased Integer := 0;
X, Y : Int_Ref (Int'Access);
Flag : Boolean := X = Y; -- illegal due to ambiguity
begin
X := Y; -- illegal due to ambiguity
X := Int_Ref'(Y); -- illegal due to ambiguity
the equality operator being called might be the equality operator for type Integer (if each of the two operands are interpreted as a generalized_reference) or it might be the equality operator for type Int_Ref (if neither is interpreted as a generalized_reference). So, by the usual RM 8.6(31) rule prohibiting such ambiguities, the declaration of Flag is illegal. Similarly, each of the two assignments might be either an Integer assignment or an Int_Ref assignment so they
are each illegal.
Nothing new here so far.
But it was recently noticed in some private discussions that this can have some unwanted and unexpected interactions with user-defined indexing.
For example,
package Float_Sets is new
Ada.Constainers.Ordered_Sets (Float);
Set : Float_Sets.Set;
use Float_Sets.Set;
function Foo (C1, C2 : Float_Sets.Cursor) return Boolean is
(Set (C1) = Set (C2)); -- illegal due to ambiguity
And if we have an indexable (non-array) type that has a specified Variable_Indexing aspect but no Constant_Indexing aspect, then we have a similar situation with assignment:
Obj (I) := Obj (J); -- illegal due to ambiguity
Obj (I) := The_Reference_Type'(Obj (J)); -- illegal due to ambiguity
[Similar ambiguities can also arise in some corner cases where the Constant_Indexing aspect *is* specified, but such cases are unimportant pathologies.]
These ambiguities seem more problematic. Users of a type with user-defined indexing do not want to have to think about the underlying implementation involving reference types. Users want to write things like
A (I) := A (J);
or
Flag : Boolean := A (I) = A (J);
and simply have them work (as opposed to being rejected as ambiguous).
This may mean that some action is warranted. Should such constructs be legal? (Yes.)
It was observed that the problematic ambiguities that come up in practice all go away if the reference type in question is limited (and that other approaches based on preference rules would introduce Beaujolais effects). Furthermore, most of the things that users typically want to do with objects of a reference type remain legal if the reference type is limited.
It is recommended (at least) that all language-defined reference types be changed to be limited. So, for example, in Ada.Containers.Vectors, the types Constant_Reference_Type and Reference_Type would be declared as "limited private" instead of "private".
Another possibility is to go further and define restrictions that would apply to user-defined types. See the !discussion section.
Replace "private" with "limited private" in the declarations of the types named either
"Reference_Type" or "Constant_Reference_Type" in the following paragraphs:
Ada.Containers.Vectors:
A.18.2 (34.1/5, 34.2/5, 79.10/5, 79.11/5, 147.1/5, 147.2/5)
Ada.Containers.Doubly_Linked_Lists:
A.18.3 (17.1/5, 17.2/5, 51.10/5, 51.11/5, 86.1/5, 86.2/5)
common to Hashed and Ordered maps:
A.18.4 (41.1/5, 41.2/5)
Ada.Containers.Hashed_Maps:
A.18.5 (17.1/5, 17.2/5, 37.11/5, 37.12/5)
Ada.Containers.Ordered_Maps:
A.18.6 (16.1/5, 16.2/5, 51.12/5, 51.13/5)
common to Hashed and Ordered sets:
A.18.7 (36.3/5, 96.1/5)
Ada.Containers.Hashed_Sets:
A.18.8 (17.2/5, 58.1/5, 59.10/5)
Ada.Containers.Ordered_Sets:
A.18.9 (16.2/5, 73.1/5, 74.10)
Ada.Containers.Multiway_Trees:
A.18.10 (28/5, 29/5, 70.10/5, 70.11/5, 122/5, 123/5)
Ada.Containers.Indefinite_Holders:
A.18.18 (16/5, 17/5, 52/5, 53/5)
For example, the declaration of Ada.Containers.Vectors.Reference_Type is changed from
type Reference_Type (Element : not null access Element_Type)
is private with … ;
to
type Reference_Type (Element : not null access Element_Type)
is limited private with … ;
These changes have the effect of modifying declarations in 23 generic packages:
Ada.Containers.Doubly_Linked_Lists
Ada.Containers.Hashed_Maps
Ada.Containers.Hashed_Sets
Ada.Containers.Ordered_Maps
Ada.Containers.Ordered_Sets
Ada.Containers.Vectors
Ada.Containers.Multiway_Trees
Ada.Containers.Indefinite_Doubly_Linked_Lists
Ada.Containers.Indefinite_Hashed_Maps
Ada.Containers.Indefinite_Hashed_Sets
Ada.Containers.Indefinite_Ordered_Maps
Ada.Containers.Indefinite_Ordered_Sets
Ada.Containers.Indefinite_Vectors
Ada.Containers.Indefinite_Multiway_Trees
Ada.Containers.Indefinite_Holders
Ada.Containers.Bounded_Doubly_Linked_Lists
Ada.Containers.Bounded_Hashed_Maps
Ada.Containers.Bounded_Hashed_Sets
Ada.Containers.Bounded_Ordered_Maps
Ada.Containers.Bounded_Ordered_Sets
Ada.Containers.Bounded_Vectors
Ada.Containers.Bounded_Multiway_Trees
Ada.Containers.Bounded_Indefinite_Holders
It is worth noting that there is no "hole" in the language here. The issue is one of usability - constructs that a user might reasonably both want and expect to work are instead rejected as illegal. There are no definitional problems with the status quo.
Even this simple proposal of changing the declarations of language-defined reference types is incompatible. It is possible that users have existing legal code that would become illegal as a result of this change. It is not known how common such affected constructs are in existing code; it seems that they would be rather unlikely. The intended uses of reference types are relatively short-lived and generally are not explicitly declared. Such uses would not be affected. [Editor’s note: There is a longer discussion of this point in the !appendix below.]
OTOH, it is also possible that users have existing ambiguous code that is incorrectly accepted by compilers and which will eventually be rejected when compiler implementation bugs are corrected. So there may already be latent compatibility issues in this area which rule changes could help bring to light.
If we want to go further than simply modifying the declarations of language-defined reference types, there are multiple approaches to consider.
Probably the simplest would be to disallow specifying the Implicit_Dereference aspect for a nonlimited type (and rechecking the full view of the type if the aspect is specified for a partial view). FWIW, this would be consistent with the old Ada95 rule that only a limited type can have an access discriminant.
A more focused approach would be to add the word "limited" to 4.1.6(3)'s rules for the Variable_Indexing aspect:
"... shall have a return type that is a {limited} reference type ..."
and append a new sentence at the end of 4.1.6(2)'s rules for the Constant_Indexing aspect (echoing the final sentence of 4.1.6(3)) :
"All such functions shall have a return type that is not a nonlimited reference type."
This would not help with the ambiguities that were known when reference types were first introduced, but such ambiguities were known then and considered acceptable. This would also not help with the ambiguity mentioned above in the case of an assignment statement where no
Constant_Indexing aspect has been specified, but perhaps that case (i.e., specifying Variable_Indexing without specifying Constant_Indexing) can be viewed as an unimportant corner case. [One might think it *would* help with that case because one of the two interpretations for the assignment statement would involve an illegal assignment to a limited and constant target object, but that's irrelevant for name resolution.]
One could imagine a name resolution rule requiring the reference object in a generalized_reference to be of a limited type. But in the past we have avoided having limitedness participate in name resolution (for example, the rule prohibiting an assignment statement that targets a limited object is not a name resolution rule).
Similarly, we have avoided having variable/constant distinctions participate in name resolution. The situation with assignment statements might be improved with a name resolution rule that if the LHS is of a reference type, then the only interpretation to be considered is as a generalized_reference. But this seems like a hack. The name resolution rules should be similar
for an assignment statement and a for call to a primitive directly-visible 2-parameter procedure having the corresponding profile. Also, that "solution" would not help with the equality case.
All of these solutions have a substantial compatibility impact. Requiring all reference types to be limited would require anyone who has defined a nonlimited reference type to change their code. Since the only examples of reference types in the (existing) RM use nonlimited reference types, and users are likely to have copied those examples, it is likely that most user-defined reference types are nonlimited. Similarly, requiring Variable_Indexing functions to return a limited reference type would run into the same problem: the examples in the current RM use a nonlimited reference type. Therefore, we have only changed the language-defined reference types to be limited types.
See !issue section.
@drepl
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Reference_Type (Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{@b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{@b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{@b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{@b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Reference_Type (Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{@b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{@b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{@b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{@b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{@b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{@b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{@b{type} Reference_Type (Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{@b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{@b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{@b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{@b{type} Reference_Type (Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{@b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null}, Use_Formal => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{null},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{@b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{@b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{@b{type} Reference_Type (Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{@b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{ @b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{@b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{@b{type} Constant_Reference_Type
(Element : @b{not null access constant} Element_Type) @b{is}
@b{limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@drepl
@xcode{@b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
@dby
@xcode{@b{type} Reference_Type
(Element : @b{not null access} Element_Type) @b{is limited private}
@b{with} Implicit_Dereference => Element,
Nonblocking, Global => @b{in out synchronized},
Default_Initial_Condition => (@b{raise} Program_Error);}
The most important test objective would be to check that the problematic ambiguities discussed in the AI are resolved so that currently-illegal assignments and comparisons of container type components are accepted.
From: Randy Brukardt
Sent: Never (written November 6, 2023)
I’ve researched the origins of the Reference_Type, and cannot find any explicit mention as to why the type was declared non-limited.
Unlike some others, I do not believe that making Reference_Types non-limited was an oversight. My best guess 12 years later is that it was because of concern about invoking the restrictions on functions that return limited types. Today, I do not believe those restrictions would cause any problems in normal use.
The original purpose of the type associated with a generalized reference was for user code to be able to be notified when a reference was no longer needed. This sort of notification is necessary if, for instance, persistent objects are to be implemented. The program would need to know when the objects need to be (and can safely be) copied back to their backing store.
The original design of the generalized reference was to have a dedicated subprogram that would be called at that point. However, it was noted that the rules were essentially the same as those for finalization, such that a short-lived controlled object would have the correct effect. Thus, we defined a wrapper object that could be a controlled object, and a way to tie the reference to that object (which turned out to already exist as well in the form of an access discriminant). This reduced the changes to the RM.
The restrictions found in 7.5 prevent a function returning a limited object from being called in certain contexts. However, the normal use of a reference type is to immediately dereference the discriminant and use only that; the rest of the object only exists to get control back when the object is destroyed. The containers use this latter property to manage the tampering checks.
Thus, the primary use of these objects is implicitly in indexing operations. These uses are allowed by the 7.5 rules in all cases, since what is being passed as a parameter and so on is a dereference of the discriminant (which designates a non-limited object). It is not intended to store a reference object, as doing so would keep the container locked against tampering for the entire time that the stored object exists.
As such, I judge that the compatibility impact of changing language-defined Reference_Types to be limited would be minimal.