CVS difference for ai12s/ai12-0111-1.txt

Differences between 1.12 and version 1.13
Log of other versions for file ai12s/ai12-0111-1.txt

--- ai12s/ai12-0111-1.txt	2016/10/06 04:06:29	1.12
+++ ai12s/ai12-0111-1.txt	2017/06/13 00:14:22	1.13
@@ -1,4 +1,4 @@
-!standard A.18.2(97.1/3)                              16-10-02  AI12-0111-1/04
+!standard A.18.2(97.1/3)                              17-06-12  AI12-0111-1/05
 !class Amendment 16-06-06
 !status work item 14-05-15
 !status received 14-02-08
@@ -15,8 +15,10 @@
 be set once when the view is created, and released when the view goes
 away.
 
-Restrict "tampering with elements" checks to containers of elements
-of an indefinite type.
+Replace any prohibition of "tampering with elements" checks with a prohibition
+of "tampering with cursors" checks for containers of elements of a definite
+type. For containers of an indefinite type, any prohibition of tampering with
+elements remains.
 
 !problem
 
@@ -53,7 +55,7 @@
 it goes away, it automatically releases the stabilization "lock" on the
 underlying vector).
 
-Two essential properties of stable containers is that they have no tampering
+Two essential properties of stable containers are that they have no tampering
 checks, and can be iterated by multiple tasks in parallel.
 
 Note that we propose to reclassify Merge as tampering with cursors,
@@ -62,16 +64,44 @@
 
 !wording
 
-Modify 18.2(92/2) (and similar paragraphs elsewhere):
+Modify A.18.2(92/2) (and similar paragraphs elsewhere):
 
   * it inserts or deletes elements of V, that is, it calls the Insert,
     Insert_Space, Clear, Delete, or Set_Length procedures{,or Merge
     procedure of an instance of Generic_Sorting,} with V as a parameter;
     or
 
-Delete 18.2(95/2-97/2) (and similar paragraphs except for Indefinite_*) talking
-about tampering with elements.
+Delete A.18.2(95/2-97/2) talking about tampering with elements.
 
+Modify A.18.2(97.1/4) as follows:
+
+  When tampering with cursors is prohibited for a particular vector
+  object V, Program_Error is propagated by a call of any
+  language-defined subprogram that is defined to tamper with the cursors
+  of V, leaving V unmodified. [Similarly, when tampering with elements is
+  prohibited for a particular vector object V, Program_Error is
+  propagated by a call of any language-defined subprogram that is
+  defined to tamper with the elements of V (or tamper with the cursors
+  of V), leaving V unmodified.] These checks are made before any other
+  defined behavior of the body of the language-defined subprogram.
+
+Add in the Indefinite_Vectors section, after A.18.11(9/4):
+* A subprogram is said to /tamper with elements/ of an indefinite
+  vector object V if:
+
+    - it tampers with cursors of V; or
+
+    - it replaces one or more elements of V, that is, it calls the
+      Replace_Element, Reverse_Elements, or Swap procedures, or the Sort
+      procedures of an instance of Generic_Sorting, with V as a parameter.
+
+  When tampering with elements is prohibited for a particular indefinite
+  vector object V, Program_Error is propagated by a call of any
+  language-defined subprogram that is defined to tamper with the
+  elements or cursors of V, leaving V unmodified.
+  These checks are made before any other defined behavior of the body of
+  the language-defined subprogram.
+
 Insert new section after A.18.2 (or in a separate area at the end of
 A.18 to avoid using 4-component numbers):
 
@@ -322,22 +352,460 @@
      private
         ...  --  not specified by the language
      end Ada.Containers.Vectors;
+
+  Upon creation, an object of type Stable.Vector marks the vector
+  designated by the Base discriminant (the /base/ vector) to disallow
+  tampering with cursors as long as the stable view of the base vector
+  exists.
+
+  The operations of the Stable subpackage correspond to the operations
+  of the enclosing generic package Vectors that do not tamper with
+  cursors. For functions that create a new vector, such as To_Vector or
+  Copy, the Stable versions of these first create a base object of the
+  Vectors.Vector type, and then create a stable vector designating that
+  base object. [Redundant: If one of these functions is used to
+  initialize a stable vector object, the return object is built in
+  place.]  The other operations of the Stable subpackage perform the
+  corresponding operation on the vector designated by the Base
+  discriminant.
+
+--------
+
+Delete A.18.3(67/2-69/2).
+
+Modify A.18.3(69.1/4) as follows:
+
+  When tampering with cursors is prohibited for a particular list object
+  L, Program_Error is propagated by a call of any language-defined
+  subprogram that is defined to tamper with the cursors of L, leaving L
+  unmodified. [Similarly, when tampering with elements is prohibited for
+  a particular list object L, Program_Error is propagated by a call of
+  any language-defined subprogram that is defined to tamper with the
+  elements of L (or tamper with the cursors of L), leaving L unmodified.]
+  These checks are made before any other defined behavior of the body of
+  the language-defined subprogram.
+
+Insert new section after A.18.3 (or in a separate area at the end of
+A.18 to avoid using 4-component numbers):
+
+  A.18.3.1 The Nested Package Containers.Doubly_Linked_Lists.Stable
+
+   The nested package Doubly_Linked_Lists.Stable
+   provides a type Stable.List that represents
+   a /stable/ list, which is one that cannot grow and shrink.  Such a
+   list can be created by calling the To_Vector or Copy functions, or
+   by establishing a /stabilized view/ of a regular Vector. While a
+   stabilized view exists, no operations that tamper with cursors are
+   permitted on the underlying regular Vector.
+
+   The operations of this package are equivalent to those for regular
+   Doubly_Linked_Lists, except that no tampering checks are performed.  If a stable
+   list is declared with the Base discriminant designating a
+   pre-existing regular list, the stable list represents a
+   stabilized view of the underlying regular list, and any operation
+   on the stable list is reflected on the underlying regular list.
+   While a stabilized view exists, any operation that tampers with
+   cursors performed on the underlying list is prohibited.  The
+   finalization of a stable list that provides such a view removes
+   this restriction on the underlying regular list Redundant[(though
+   some other restriction might exist due to other concurrent iterations
+   or stabilized views)].
+
+   If a stable list is declared without specifying Base, the object must
+   be initialized. The initializing expression of
+   the stable list, Redundant[typically a call on To_Vector or
+   Copy], determines the Length of the list. By default the Length
+   is zero. The Length of a stable list never changes after
+   initialization.
+
+[Author's note: Below, we have left in the original paragraph numbers
+from the Vector container because we thought they might be useful, and
+mostly because we are too lazy to remove them.]
+
+        ...  --  enclosing package Ada.Containers.Doubly_Linked_Lists
+
+        package Stable is
+
+8/3        type List (Base : not null access Doubly_Linked_Lists.List) is
+              tagged limited private
+              with Constant_Indexing => Constant_Reference,
+                   Variable_Indexing => Reference,
+                   Default_Iterator  => Iterate,
+                   Iterator_Element  => Element_Type;
+           pragma Preelaborable_Initialization(List);
+
+9/2        type Cursor is private;
+           pragma Preelaborable_Initialization(Cursor);
+
+10/2       Empty_List : constant List;
+
+11/2       No_Element : constant Cursor;
+
+11.1/3     function Has_Element (Position : Cursor) return Boolean;
+
+11.2/3     package List_Iterator_Interfaces is new
+               Ada.Iterator_Interfaces (Cursor, Has_Element);
+
+12/2       function "=" (Left, Right : List) return Boolean;
+
+21/2       function Length (Container : List) return Count_Type;
+
+23/2       function Is_Empty (Container : List) return Boolean;
+
+28/2       function Element (Position : Cursor) return Element_Type;
+
+30/2       procedure Replace_Element (Container : in out List;
+                                      Position  : in     Cursor;
+                                      New_item  : in     Element_Type);
+
+32/2       procedure Query_Element
+             (Position : in Cursor;
+              Process  : not null access procedure (Element : in Element_Type));
+
+34/2       procedure Update_Element
+             (Container : in out List;
+              Position  : in     Cursor;
+              Process   : not null access procedure
+                              (Element : in out Element_Type));
+
+34.1/3     type Constant_Reference_Type
+                 (Element : not null access constant Element_Type) is private
+              with Implicit_Dereference => Element;
+
+34.2/3     type Reference_Type
+         (Element : not null access Element_Type) is private
+              with Implicit_Dereference => Element;
+
+34.5/3     function Constant_Reference (Container : aliased in List;
+                                        Position  : in Cursor)
+              return Constant_Reference_Type;
+
+34.6/3     function Reference (Container : aliased in out List;
+                               Position  : in Cursor)
+              return Reference_Type;
+
+34.7/3     procedure Assign (Target : in out List;
+                             Source : in List)
+
+           procedure Assign (Target : in out Doubly_Linked_Lists.List;
+                             Source : in List);
+
+34.8/3     function Copy (Source : List)
+              return List;
+
+           function Copy (Source : Doubly_Linked_Lists.List)
+              return List;
+
+54/2       procedure Reverse_Elements (Container : in out List);
+
+56/2       procedure Swap (Container : in out List;
+                           I, J      : in     Cursor);
+
+58/2       function First (Container : List) return Cursor;
+
+59/2       function First_Element (Container : List)
+              return Element_Type;
+
+61/2       function Last (Container : List) return Cursor;
+
+62/2       function Last_Element (Container : List)
+              return Element_Type;
+
+63/2       function Next (Position : Cursor) return Cursor;
+
+64/2       procedure Next (Position : in out Cursor);
+
+65/2       function Previous (Position : Cursor) return Cursor;
+
+66/2       procedure Previous (Position : in out Cursor);
+
+68/2       function Find (Container : List;
+                          Item      : Element_Type;
+                          Position  : Cursor := No_Element)
+              return Cursor;
+
+70/2       function Reverse_Find (Container : List;
+                                  Item      : Element_Type;
+                                  Position  : Cursor := No_Element)
+              return Cursor;
+
+71/2       function Contains (Container : List;
+                              Item      : Element_Type) return Boolean;
 
-Upon creation, an object of type Stable.Vector marks the vector
-designated by the Base discriminant (the /base/ vector) to disallow
-tampering with cursors as long as the stable view of the base vector
-exists.
-
-The operations of the Stable subpackage correspond to the operations of
-the enclosing generic package Vectors that do not tamper with cursors.
-For functions that create a new vector, such as To_Vector or Copy, the
-Stable version of these first create a base object of the Vectors.Vector
-type, and then create a stable vector designating that base object.
-[Redundant: If one of these functions is used to initialize a stable
-vector object, the return object is built in place.]  The other
-operations of the Stable subpackage perform the corresponding operation
-on the vector designated by the Base discriminant.
+73/2       procedure  Iterate
+             (Container : in List;
+              Process   : not null access procedure (Position : in Cursor));
+
+74/2       procedure Reverse_Iterate
+             (Container : in List;
+              Process   : not null access procedure (Position : in Cursor));
+
+74.1/3     function Iterate (Container : in List)
+              return List_Iterator_Interfaces.Reversible_Iterator'Class;
+
+74.2/3     function Iterate (Container : in List; Start : in Cursor)
+              return List_Iterator_Interfaces.Reversible_Iterator'Class;
+
+75/2       generic
+              with function "<" (Left, Right : Element_Type)
+                 return Boolean is <>;
+           package Generic_Sorting is
+
+76/2          function Is_Sorted (Container : List) return Boolean;
+
+77/2          procedure Sort (Container : in out List);
+
+79/2       end Generic_Sorting;
+
+80/2    private
+
+81/2       ... -- not specified by the language
+
+82/2    end Stable;
+
+     private
+        ...  --  not specified by the language
+     end Ada.Containers.Doubly_Linked_Lists;
+
+  Upon creation, an object of type Stable.List marks the list designated
+  by the Base discriminant (the /base/ list) to disallow tampering with
+  cursors as long as the stable view of the base list exists.
+
+  The operations of the Stable subpackage correspond to the operations
+  of the enclosing generic package Doubly_Linked_Lists that do not
+  tamper with cursors. For functions that create a new list, such as
+  Copy, the Stable versions of these first create a base object of the
+  Doubly_Linked_Lists.List type, and then create a stable list
+  designating that base object. [Redundant: If one of these functions is
+  used to initialize a stable list object, the return object is built in
+  place.]  The other operations of the Stable subpackage perform the
+  corresponding operation on the list designated by the Base
+  discriminant.
+
+-----
+
+
+In the section on Indefinite_Doubly_Linked_Lists, A.18.12, add after para 8/4:
+
+  * A subprogram is said to tamper with elements of an indefinite
+    list object L if:
+
+    - it tampers with cursors of L; or
+
+    - it replaces one or more elements of L, that is, it calls the
+      Replace_Element or Swap procedures with L as a parameter.
+
+  When tampering with elements is prohibited for a particular list
+  object L, Program_Error is propagated by a call of any
+  language-defined subprogram that is defined to tamper with the
+  elements or cursors of L, leaving L unmodified. These checks are
+  made before any other defined behavior of the body of the
+  language-defined subprogram.
+
+Delete A.18.10(87/3-89/3) in section on Multiway_Trees
+Modify A.18.10(90/4):
+
+  When tampering with cursors is prohibited for a particular tree object
+  T, Program_Error is propagated by a call of any language-defined
+  subprogram that is defined to tamper with the cursors of T, leaving T
+  unmodified. [Similarly, when tampering with elements is prohibited for
+  a particular tree object T, Program_Error is propagated by a call of
+  any language-defined subprogram that is defined to tamper with the
+  elements of T (or tamper with the cursors of T), leaving T
+  unmodified.] These checks are made before any other defined behavior
+  of the body of the language-defined subprogram.
+
+In the section on Indefinite_Multiway_Trees, add after A.18.17(8/4):
+
+  * A subprogram is said to tamper with elements of a tree object T if:
+
+     - it tampers with cursors of T; or
+
+     - it replaces one or more elements of T, that is, it calls
+       the Replace_Element or Swap procedures with T as a parameter.
+
+  When tampering with elements is prohibited for a particular indefinite tree
+  object T, Program_Error is propagated by a call of any
+  language-defined subprogram that is defined to tamper with the
+  elements or cursors of T, leaving T unmodified.
+  These checks are made before any other defined behavior of the body of
+  the language-defined subprogram.
+
+---
+
+In section A.18.4 on Maps, modify A.18.4(13/2) as follows:
+  * A subprogram is said to tamper with elements of a map object M if {the
+    formal Element_Type is indefinite (see A.18.13 and A.18.14), and}:
+
+Insert new section after A.18.5 (or in a separate area at the end of
+A.18 to avoid using 4-component numbers):
+
+  A.18.5.1 The Nested Package Containers.Hashed_Maps.Stable
+
+   The nested package Hashed_Maps.Stable
+   provides a type Stable.Map that represents
+   a /stable/ map, which is one that cannot grow and shrink.  Such a
+   map can be created by calling the Copy functions, or
+   by establishing a /stabilized view/ of a regular Map. While a
+   stabilized view exists, no operations that tamper with cursors are
+   permitted on the underlying regular Map.
+
+   The operations of this package are equivalent to those for regular
+   Hashed_Maps, except that no tampering checks are performed.  If a stable
+   map is declared with the Base discriminant designating a
+   pre-existing regular map, the stable map represents a
+   stabilized view of the underlying regular map, and any operation
+   on the stable map is reflected on the underlying regular map.
+   While a stabilized view exists, any operation that tampers with
+   cursors performed on the underlying map is prohibited.  The
+   finalization of a stable map that provides such a view removes
+   this restriction on the underlying regular map Redundant[(though
+   some other restriction might exist due to other concurrent iterations
+   or stabilized views)].
+
+   If a stable map is declared without specifying Base, the object must
+   be initialized. The initializing expression of
+   the stable map, Redundant[typically a call on
+   Copy], determines the Length of the map. By default the Length
+   is zero. The Length of a stable map never changes after
+   initialization.
+
+   The Containers.Hashed_Maps.Stable subpackage is based on the Hashed_Maps
+   package, but with the following changes:
+
+     Type Map is declared as follows:
+
+           type Map (Base : not null access Hashed_Maps.Map) is
+              tagged limited private
+              with Constant_Indexing => Constant_Reference,
+                   Variable_Indexing => Reference,
+                   Default_Iterator  => Iterate,
+                   Iterator_Element  => Element_Type;
+           pragma Preelaborable_Initialization(Map);
+
+     The operations Clear, Assign, Move, Insert, Include, Exclude, and Delete
+     are omitted.
+
+     Upon creation, an object of type Stable.Map marks the map
+     designated by the Base discriminant (the /base/ map) to disallow
+     tampering with cursors as long as the stable view of the base map
+     exists.
+
+     The operations of the Stable subpackage correspond to the
+     operations of the enclosing generic package Hashed_Maps
+     that do not tamper with cursors. For functions that create a new
+     list, such as Copy, the Stable versions of these first create a
+     base object of the Hashed_Maps.Map type, and then create a
+     stable map designating that base object. [Redundant: If one of
+     these functions is used to initialize a stable map object, the
+     return object is built in place.]  The other operations of the
+     Stable subpackage perform the corresponding operation on the map
+     designated by the Base discriminant.
 
+----
+Insert new section after A.18.6 (or in a separate area at the end of
+A.18 to avoid using 4-component numbers):
+
+  A.18.6.1 The Nested Package Containers.Ordered_Maps.Stable
+
+   The nested package Ordered_Maps.Stable
+   provides a type Stable.Map that represents
+   a /stable/ map, which is one that cannot grow and shrink.  Such a
+   map can be created by calling the Copy functions, or
+   by establishing a /stabilized view/ of a regular Map. While a
+   stabilized view exists, no operations that tamper with cursors are
+   permitted on the underlying regular Map.
+
+   The operations of this package are equivalent to those for regular
+   Ordered_Maps, except that no tampering checks are performed.  If a stable
+   map is declared with the Base discriminant designating a
+   pre-existing regular map, the stable map represents a
+   stabilized view of the underlying regular map, and any operation
+   on the stable map is reflected on the underlying regular map.
+   While a stabilized view exists, any operation that tampers with
+   cursors performed on the underlying map is prohibited.  The
+   finalization of a stable map that provides such a view removes
+   this restriction on the underlying regular map Redundant[(though
+   some other restriction might exist due to other concurrent iterations
+   or stabilized views)].
+
+   If a stable map is declared without specifying Base, the object must
+   be initialized. The initializing expression of
+   the stable map, Redundant[typically a call on
+   Copy], determines the Length of the map. By default the Length
+   is zero. The Length of a stable map never changes after
+   initialization.
+
+   The Containers.Ordered_Maps.Stable subpackage is based on the Ordered_Maps
+   package, but with the following changes:
+
+     Type Map is declared as follows:
+
+           type Map (Base : not null access Ordered_Maps.Map) is
+              tagged limited private
+              with Constant_Indexing => Constant_Reference,
+                   Variable_Indexing => Reference,
+                   Default_Iterator  => Iterate,
+                   Iterator_Element  => Element_Type;
+           pragma Preelaborable_Initialization(Map);
+
+     The operations Clear, Assign, Move, Insert, Include, Exclude, and Delete
+     are omitted.
+
+     Upon creation, an object of type Stable.Map marks the map
+     designated by the Base discriminant (the /base/ map) to disallow
+     tampering with cursors as long as the stable view of the base map
+     exists.
+
+     The operations of the Stable subpackage correspond to the
+     operations of the enclosing generic package Ordered_Maps
+     that do not tamper with cursors. For functions that create a new
+     list, such as Copy, the Stable versions of these first create a
+     base object of the Ordered_Maps.Map type, and then create a
+     stable map designating that base object. [Redundant: If one of
+     these functions is used to initialize a stable map object, the
+     return object is built in place.]  The other operations of the
+     Stable subpackage perform the corresponding operation on the map
+     designated by the Base discriminant.
+
+----
+In section A.18.7 on Sets, delete A.18.7(13/2 and 13/3),
+and modify A.18.7(14.1/4) as follows:
+
+   When tampering with cursors {or tampering with elements} is prohibited
+   for a particular set object S, Program_Error is propagated by a call
+   of any language-defined subprogram that is defined to tamper with the
+   cursors of S, leaving S unmodified. [Similarly, when tampering with
+   elements is prohibited for a particular set object S, Program_Error
+   is propagated by a call of any language-defined subprogram that is
+   defined to tamper with the elements of S (or tamper with the cursors
+   of S), leaving S unmodified.] These checks are made before any other
+   defined behavior of the body of the language-defined subprogram.
+
+Insert new section after A.18.8 (or in a separate area at the end of
+A.18 to avoid using 4-component numbers):
+
+  A.18.8.1 The Nested Package Containers.Hashed_Sets.Stable
+
+... analogous to Hashed_Maps.Stable, but list of omitted operations is instead:
+
+  Procedures Reserve_Capacity, Clear, Replace_Element, Assign, Move, Insert,
+  Include, Replace, Exclude, Delete, Union, Intersection, Difference, and
+  Symmetric_Difference are omitted, as is the nested generic package
+  Generic_Keys.
+
+Insert new section after A.18.9 (or in a separate area at the end of
+A.18 to avoid using 4-component numbers):
+
+  A.18.9.1 The Nested Package Containers.Ordered_Sets.Stable
+
+... analogous to Ordered_Maps.Stable, but list of omitted operations is instead:
+
+  Procedures Reserve_Capacity, Clear, Replace_Element, Assign, Move,
+  Insert, Include, Replace, Exclude, Delete, Delete_First, Delete_Last,
+  Union, Intersection, Difference, and Symmetric_Difference are omitted,
+  as is the nested generic package Generic_Keys.
+
 !discussion
 
 Tampering was primarily intended to prevent erroneous/unspecified behavior.
@@ -2663,8 +3131,8 @@
 From: Tucker Taft
 Sent: Monday, October 3, 2016  3:35 PM
 
-> Why do you need the Base to be an access discriminant ? The rationale 
-> may be obvious, it is not mentioned in the AI, but to my mind it 
+> Why do you need the Base to be an access discriminant ? The rationale
+> may be obvious, it is not mentioned in the AI, but to my mind it
 > mostly causes problems in the implementation.
 
 Without an access discriminant, I can't imagine how the user will specify which
@@ -2689,7 +3157,7 @@
 Sent: Monday, October 3, 2016  3:56 PM
 
 > Without an access discriminant, I can't imagine how the user will specify
-> which unstable vector the stable vector will control. 
+> which unstable vector the stable vector will control.
 
 Via a constructor function ? That would be a better option I think, make the
 type completely private, and have one/several constructor functions if you
@@ -2701,18 +3169,18 @@
 function Stable_View (Self : Vector) return Stable.Vector;
 
 
->>... How do you plan to define Empty_Vector, knowing that Base can't be null, 
->>and that you cannot use Vectors.Empty_Vector because it will appear later ? 
+>>... How do you plan to define Empty_Vector, knowing that Base can't be null,
+>>and that you cannot use Vectors.Empty_Vector because it will appear later ?
 
 >Good point.  We probably have to make Empty_Vector into a parameterless
->function, now that this is a nested package.  E.g.: 
+>function, now that this is a nested package.  E.g.:
 >
->   function Empty_Vector return Vector is 
->   begin 
->      return Result : Vector(Base => new Vectors.Vector'(Empty_Vector)); 
->   end Empty_Vector; 
+>   function Empty_Vector return Vector is
+>   begin
+>      return Result : Vector(Base => new Vectors.Vector'(Empty_Vector));
+>   end Empty_Vector;
 >
->The result would be "built in place" at the point of call. 
+>The result would be "built in place" at the point of call.
 
 I think this is a bit kludgey, I'd like to be sure that the access
 discriminant is needed first.
@@ -2722,8 +3190,8 @@
 From: Tucker Taft
 Sent: Monday, October 3, 2016  4:18 PM
 
-> Via a constructor function ? That would be a better option I think, 
-> make the type completely private, and have one/several constructor 
+> Via a constructor function ? That would be a better option I think,
+> make the type completely private, and have one/several constructor
 > functions if you need to enable the user to construct them directly.
 
 Not quite sure how that would work from an accessibility point of view.
@@ -2732,7 +3200,7 @@
 object be aliased, and since Vector is a tagged type, when passed as a
 parameter it is always aliased.
 
-> Also what do you mean by user ? To my mind a stable container can only 
+> Also what do you mean by user ? To my mind a stable container can only
 > be constructed via functions on the container itself, something like:
 >
 > function Stable_View (Self : Vector) return Stable.Vector;
@@ -2747,10 +3215,10 @@
        Stable_X : My_Vectors.Stable.Vector(Base => X'Access);
        ...
 
->>> ... How do you plan to define Empty_Vector, knowing that Base can't 
+>>> ... How do you plan to define Empty_Vector, knowing that Base can't
 >>> be null, and that you cannot use Vectors.Empty_Vector because it will appear later ?
 >>
->> Good point.  We probably have to make Empty_Vector into a 
+>> Good point.  We probably have to make Empty_Vector into a
 >> parameterless function, now that this is a nested package.  E.g.:
 >>
 >>    function Empty_Vector return Vector is
@@ -2760,7 +3228,7 @@
 >>
 >> The result would be "built in place" at the point of call.
 >
-> I think this is a bit kludgey, I'd like to be sure that the access 
+> I think this is a bit kludgey, I'd like to be sure that the access
 > discriminant is needed first.
 
 This situation is in some sense exactly what access discriminants were
@@ -2772,9 +3240,9 @@
 From: Bob Duff
 Sent: Monday, October 3, 2016  4:24 PM
 
-> Good point.  We probably have to make Empty_Vector into a 
+> Good point.  We probably have to make Empty_Vector into a
 > parameterless function, now that this is a nested package.  E.g.:
-> 
+>
 >     function Empty_Vector return Vector is
 
 Functions are better anyway, because they can be overloaded.
@@ -2806,7 +3274,7 @@
 
 ...
 > Functions are better anyway, because they can be overloaded.
-> It's annoying when the compiler complains, "Which Empty_Vector did you 
+> It's annoying when the compiler complains, "Which Empty_Vector did you
 > mean?"  "The one of the right type, of course, YA BIG DUMMY!!"  ;-)
 
 There'd be no major problem in allowing constants to be overloaded (the
@@ -2855,7 +3323,7 @@
 From: Raphael Amiard
 Sent: Monday, October 3, 2016  6:06 PM
 
-> Good point.  We probably have to make Empty_Vector into a 
+> Good point.  We probably have to make Empty_Vector into a
 > parameterless function, now that this is a nested package. E.g.:
 >
 >    function Empty_Vector return Vector is
@@ -2863,7 +3331,7 @@
 >       return Result : Vector(Base => new Vectors.Vector'(Empty_Vector));
 >    end Empty_Vector;
 >
-> The result would be "built in place" at the point of call. 
+> The result would be "built in place" at the point of call.
 
 I don't understand though, are you thinking about actually allocating a new
 empty vector copy every time the users calls Stable.Empty_Vector?
@@ -2917,19 +3385,19 @@
 From: Tucker Taft
 Sent: Monday, October 3, 2016  9:35 PM
 
->> Yes, although this is a "co-extension" so that its lifetime lasts 
->> only as long as the enclosing object -- it isn't necessarily on the 
+>> Yes, although this is a "co-extension" so that its lifetime lasts
+>> only as long as the enclosing object -- it isn't necessarily on the
 >> heap -- it is allocated where the enclosing object is allocated.
 >
-> Is this implemented by GNAT though, or by any other Ada compiler ? 
+> Is this implemented by GNAT though, or by any other Ada compiler ?
 > That would need to be checked in my opinion,
 
 This might justify GNAT fixing this, if they don't do it correctly now.   But
 see below -- simpler is to delete Empty_Vector from the package.
 
-> ... because however uncommon checking a stable vector against the 
-> empty vector would be, it could still happen in a time critical loop 
-> where I certainly would not expect an allocation to happen, with all 
+> ... because however uncommon checking a stable vector against the
+> empty vector would be, it could still happen in a time critical loop
+> where I certainly would not expect an allocation to happen, with all
 > associated cons (System call, context switch, unbounded time operation).
 
 If that is a real concern, I would suggest we omit "Empty_Vector" completely
@@ -2938,11 +3406,11 @@
 reason, in the absence of an Empty_Vector operation, you could do it using
 To_Vector() or Copy().
 
-> If it is, I only have a theoretical objection against such a solution 
-> (the code is too complicated for what it does). If it is not, I also 
+> If it is, I only have a theoretical objection against such a solution
+> (the code is too complicated for what it does). If it is not, I also
 > have a practical one :)
 >
-> The reason we're in this situation in the first place is that 
+> The reason we're in this situation in the first place is that
 > performance was not originally taken into consideration in the design of the
 > containers.
 
@@ -2951,7 +3419,7 @@
 concern.  It may be that we just didn't understand the usage patterns, or the
 overall impact of tampering checks.  And as Randy likes to remind us, it is
 the implementation of references as controlled objects rather than tampering
-checks per se that can be the source of a lot of the overhead. 
+checks per se that can be the source of a lot of the overhead.
 These kind of references didn't exist when containers were first designed.
 
 > ... Let's not do the same
@@ -2968,21 +3436,21 @@
 From: Raphael Amiard
 Sent: Monday, October 3, 2016  10:01 PM
 
-> If that is a real concern, I would suggest we omit "Empty_Vector" 
-> completely from the package.  The right way to check if a vector is 
-> empty is using "Is_Empty" and if you want to create a stable empty 
-> vector for some bizarre reason, in the absence of an Empty_Vector 
+> If that is a real concern, I would suggest we omit "Empty_Vector"
+> completely from the package.  The right way to check if a vector is
+> empty is using "Is_Empty" and if you want to create a stable empty
+> vector for some bizarre reason, in the absence of an Empty_Vector
 > operation, you could do it using
 > To_Vector() or Copy().
 
 I think this is the best option indeed !
 
-> That is a little unfair, I would say.  There was an implementation of 
-> containers from day one of the design, and performance was a 
-> significant concern.  It may be that we just didn't understand the 
-> usage patterns, or the overall impact of tampering checks.  And as 
-> Randy likes to remind us, it is the implementation of references as 
-> controlled objects rather than tampering checks per se that can be the 
+> That is a little unfair, I would say.  There was an implementation of
+> containers from day one of the design, and performance was a
+> significant concern.  It may be that we just didn't understand the
+> usage patterns, or the overall impact of tampering checks.  And as
+> Randy likes to remind us, it is the implementation of references as
+> controlled objects rather than tampering checks per se that can be the
 > source of a lot of the overhead. These kind of references didn't exist when
 > containers were first designed.
 
@@ -2992,10 +3460,10 @@
 >> ... Let's not do the same
 >> mistake again.
 >
-> Agreed.  But on the other hand, let's not worry too much about 
-> performance implications of misusing the operations.  In any case, if 
-> we remove Empty_Vector from the package, I think we simplify the 
-> interface and eliminate a way that a naive user might waste a lot of 
+> Agreed.  But on the other hand, let's not worry too much about
+> performance implications of misusing the operations.  In any case, if
+> we remove Empty_Vector from the package, I think we simplify the
+> interface and eliminate a way that a naive user might waste a lot of
 > energy creating an empty vector just to use it to compare against some other
 > vector.
 
@@ -3006,8 +3474,8 @@
 From: Randy Brukardt
 Sent: Monday, October 3, 2016  10:04 PM
 
-> >> Yes, although this is a "co-extension" so that its lifetime lasts 
-> >> only as long as the enclosing object -- it isn't necessarily on the 
+> >> Yes, although this is a "co-extension" so that its lifetime lasts
+> >> only as long as the enclosing object -- it isn't necessarily on the
 > >> heap -- it is allocated where the enclosing object is allocated.
 
 "coextension" (no hyphen). And yes, Raphael, it is a first-class part of
@@ -3019,7 +3487,7 @@
 real issues. (I hate coextensions with a passion...)
 
 ...
-> If that is a real concern, I would suggest we omit "Empty_Vector" 
+> If that is a real concern, I would suggest we omit "Empty_Vector"
 > completely from the package.
 
 That seems to be the correct solution. What possible purpose is there for
@@ -3040,14 +3508,14 @@
 From: Raphael Amiard
 Sent: Monday, October 3, 2016  10:28 PM
 
-> OTOH, I can't imagine why we would care how an operation that would 
-> never be used is implemented. Heck, it could permanently leak memory 
+> OTOH, I can't imagine why we would care how an operation that would
+> never be used is implemented. Heck, it could permanently leak memory
 > and send pinups to Ada mailing lists
 
 As the guy in charge of prototyping, challenge accepted !
 
->   and no one other than a possible ACATS test would ever care. So this 
-> has to be one of the silliest tempest-in-a-teapots ARG discussions 
+>   and no one other than a possible ACATS test would ever care. So this
+> has to be one of the silliest tempest-in-a-teapots ARG discussions
 > I've heard in a while.
 
 Well, I'll take pride in that if in nothing else :)
@@ -3085,7 +3553,7 @@
 >
 >    declare
 >       Stable_X : My_Vectors.Stable.Vector(Base => X'Access);
->       ... 
+>       ...
 
 I've made good progress with the implementation, to the point where I'm writing
 use cases, and looking back on it, this seems like a verbose way to declare a
@@ -3127,7 +3595,7 @@
 Sent: Tuesday, October 4, 2016  10:46 AM
 
 > Here is an update on the stable containers AI. I donít believe Raphael had
-time to prototype this. 
+time to prototype this.
 
 So, Iím more or less done prototyping this, will clean up the code and
 send it here when Iím done.
@@ -3161,14 +3629,14 @@
 
    for El of Vec loop
       El := El + 1;
-      Sum := Sum + Long_Long_Integer (El);   
+      Sum := Sum + Long_Long_Integer (El);
    end loop;
 
    Put_Line ("SUM : " & Sum'Image);
    Put_Line ("Time = " & Duration'Image (Clock - T));
 
    Put_Line ("Iterating on stable vector ..");
-   T := Clock;   
+   T := Clock;
    Sum := 0;
 
    declare
@@ -3222,7 +3690,7 @@
 >     Here is an update on the stable containers AI. I donít believe Raphael
 >     had time to prototype this.
 >
-> So, Iím more or less done prototyping this, will clean up the code and 
+> So, Iím more or less done prototyping this, will clean up the code and
 > send it here when Iím done.
 
 Great!
@@ -3234,9 +3702,9 @@
 >
 > Has the following output:
 >
-> |Inserting elements into Vector .. Iterating on regular vector .. SUM 
+> |Inserting elements into Vector .. Iterating on regular vector .. SUM
 > |: 50000015000014 Time
-> = 0.796831000 Iterating on stable vector .. SUM : 50000025000018 Time 
+> = 0.796831000 Iterating on stable vector .. SUM : 50000025000018 Time
 > = 0.045607000 |
 
 Nice!  But should I be worried that they result in different SUM values???
@@ -3304,12 +3772,12 @@
 Sent: Tuesday, October 4, 2016  11:27 AM
 
 ...
->  So you will need to add a 
+>  So you will need to add a
 > flag to the stable vector which indicates this.  E.g. add a component:
 >
 >     Boolean : Deallocate_Vector_On_Finalization := False;
 >
-> It needs to default to False so a Stable.Vector without an explicit 
+> It needs to default to False so a Stable.Vector without an explicit
 > initialization will know not to deallocate the vector it refers to.
 
 Already implemented it like that, and realized at the end it should be
@@ -3371,6 +3839,39 @@
 
 Thanks RaphaŽl for putting this together so quickly. Probably will want to
 define a new aspect rather than somehow treating a nested package called
-Stable as something magical. 
+Stable as something magical.
+
+***************************************************************
+
+From: Tucker Taft
+Sent: Monday, June 12, 2017  4:46 PM
+
+Update given below. [This is version /05 of the AI - Editor.]
+ I repeated the full spec for Doubly_Linked_Lists.Stable, but then simplified
+later additions by describing the differences, rather than duplicating the
+spec.  That might be the right way to do Vectors.Stable and
+Doubly_Linked_Lists.Stable as well.  I tried two different ways to deal with
+tampering with elements.  Probably we should pick one or the other.
+
+***************************************************************
+
+From: Randy Brukardt
+Sent: Monday, June 12, 2017  7:16 PM
+
+> ... I tried two different ways to
+> deal with tampering with elements.  Probably we should pick one or the
+> other.
+
+I only saw one, which clause used a different method than Vectors?
+
+Secondly, while you have a nice definition of tampering with elements and
+prohibiting tampering with elements in the Indefinite_Vector, I didn't see any
+text that defines what operations prohibit tampering with elements (since you
+changed the original definitions to "tampering with cursors"). Humm, actually, I
+can't find where you changed the original definitions. But you have to do that,
+as "tampering with elements" is no longer defined in A.18.2, so you can't use it
+in A.18.2.
+
+Otherwise, a quick check looks OK.
 
 ***************************************************************

Questions? Ask the ACAA Technical Agent