CVS difference for ais/ai-30302.txt

Differences between 1.15 and version 1.16
Log of other versions for file ais/ai-30302.txt

--- ais/ai-30302.txt	2005/01/07 03:07:48	1.15
+++ ais/ai-30302.txt	2005/04/15 04:31:25	1.16
@@ -26218,23 +26218,2482 @@
 ****************************************************************
 
 From: Matthew Heaney
-Sent: Friday, September 2, 2004  9:31 AM
+Sent: Sunday, April 3, 2005 10:30 PM
 
+Georg Bauhaus forwarded this comment to me.  Several lines of text say:
+
+    Program_Error is propagated unless Before is equal
+       to No_Element or designated an element in Target.
+
+He was asking about the mixed use of tense.  It looks like it should say
+"designates an element...".
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Wednesday, March 23, 2005  11:14 PM
+
+I've been reading the API described here:
+
+<http://www.ada-auth.org/cgi-bin/cvsweb.cgi/AIs/AI-20302.TXT?rev=1.16>
+
+The first line of that file says:
+
+05-02-02  AI95-00302-03/10
+
+I don't know if this is the most up-to-date API, but I wanted to get this in
+the queue anyway.
+
+Each comment is bracked by "MJH:" and "ENDMJH." pairs, and immediately
+follows the API text to which it refers.
+
+A little after the declaration of the spec of the vector in A.18.2, the API
+says:
+
+ * it inserts or deletes elements of V, that is, it calls the Insert,
+   Insert_Space, Clear, Delete, Delete_Last, or Set_Length procedures with V
+   as a parameter; or
+
+MJH:
+
+Do you want to add Delete_First to this list?
+
+ENDMJH.
+
+
+And a little after that, then API says:
+
+Some operations are assumed to not change elements. For such an operation, a
+subprogram is said to *tamper with elements* of a vector object V if:
+
+   * it tampers with cursors of V; or
+   * it modifies one or more elements of V, that is, it calls the
+     Replace_Element, Update_Element, or Swap procedures or an
+     instance of Generic_Sort with V as a parameter.
+
+   AARM Note:
+   Swap and Generic_Sort copy elements rather than reordering them, so
+   they can be allowed for Iterate.
+
+MJH:
+
+I don't see then how you can implement a tamper-resistent vector using a
+single internal counter (see the AARM note the follows the description of
+the Iterate operation).  You're saying that calling Generic_Sort is allowed
+during Iterate, but not allowed during (say) Query_Element.  So how can you
+use a single counter to handle both cases?  (But maybe there is a way that I
+just haven't figured out.)
+
+Perhaps it is the case that you can't call Swap during Iterate.  I think
+it's true that in our model, a cursor designates an element.  If you sort
+during Iterate (inside the call to Process.all), then the cursor parameter
+won't continue to designate the same element after it gets moved into its
+new sort position (since a cursor is merely an array index).
+
+ENDMJH.
+   
+
+procedure Set_Length (Container : in out Vector;
+                      Length    : in     Count_Type);
+
+
+MJH:
+
+If Set_Length is called by Process.all during Iterate, and the
+requested length is the same as the current length, then is this an
+error?  Or is the implementation still required to raise PE?
+
+ENDMJH.
+
+
+procedure Delete (Container : in out Vector;
+                  Index     : in     Extended_Index;
+                  Count     : in     Count_Type := 1);
+
+If Index is not in the range First_Index (Container) .. Last_Index
+(Container),
+then Constraint_Error is propagated. If Count is 0, Delete has no effect.
+
+MJH:
+
+I think these two sentences are backwards.  If Count is 0, then it
+doesn't really matter what value Index has.  (Right?)
+
+ENDMJH.
+
+
+procedure Delete (Container : in out Vector;
+                  Position  : in out Cursor;
+                  Count     : in     Count_Type := 1);
+
+If Position equals No_Element, then Constraint_Error is propagated. If
+Position
+does not designate an element in Container, then Program_Error is
+propagated.
+Otherwise, Delete (Container, To_Index (Position), Count) is called.
+
+MJH:
+
+Is that first sentence true even when Count = 0?  Shouldn't Count=0 be a
+no-op?
+
+ENDMJH.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Thursday, March 24, 2005  12:51 PM
+
+Here's the section of the vectors spec for Query_Element:
+
+
+procedure Query_Element
+   (Container : in Vector;
+    Index     : in Index_Type;
+    Process   : not null access procedure (Element : in Element_Type));
+
+...Program_Error is propagated if Process.all tampers with the elements 
+of Container. Any exception raised by Process.all is propagated.
+
+
+procedure Query_Element
+   (Position : in Cursor;
+    Process  : not null access procedure (Element : in Element_Type));
+
+...Program_Error is propagated if Process.all tampers with the elements 
+of Container. Any exception raised by Process.all is propagated.
+
+AARM Note: The tamper with the elements check is intended to prevent the
+Element parameter of Process from being modified or deleted outside of
+Process. The check prevent data loss (if Element_Type is passed by copy)
+or erroneous execution (if Element_Type is an unconstrained type in
+an indefinite container).
+
+
+MJH:
+
+There are two issues: changing the cardinality of the vector container, 
+and changing the value of an element.
+
+It's relatively cheap to check for changes of cardinality during 
+iteration, using the counter as described in the AARM Note near the 
+description of Iterate.
+
+However, the API fragment I have cited above wants to make a stronger 
+check: that a specific element isn't updated while Query_Elem is in 
+progress.  How can you make this check without having a separate counter 
+for each vector element?
+
+What is the exact intent of the "tampers with elements" check?  To 
+monitor whether any element is being manipulated, or to monitor specific 
+elements?
+
+If the former (any element), then you do intend to restrict the user's 
+ability to manipulate other elements while a query of an element is in 
+progress?  If so, then it would appear that description of the 
+implementation of the check (using a single internal counter) is 
+incorrect, since two internal counters are necessary.
+
+If the latter (specific elements), then how can you monitor specific 
+elements without using a per-element counter?
+
+You have the AARM Note cited above that gives a rationale for the 
+tampers-with-element check, but do we really want to do this?  If a user 
+  is querying an element, and then manipulates that same element by 
+calling other operations inside Process.all, then isn't this just a case 
+of aliasing?  Why is this the container's problem?
+
+ENDMJH.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 24, 2005  6:09 PM
+
+Matt wrote:
+
+> I've been reading the API described here:
+>
+> <http://www.ada-auth.org/cgi-bin/cvsweb.cgi/AIs/AI-20302.TXT?rev=1.16>
+>
+> The first line of that file says:
+>
+> 05-02-02  AI95-00302-03/10
+>
+> I don't know if this is the most up-to-date API, but I wanted to get this in
+> the queue anyway.
+
+There is a slightly newer version with some typos fixed, but it is
+essentially correct.
+
+> Each comment is bracked by "MJH:" and "ENDMJH." pairs, and immediately
+> follows the API text to which it refers.
+>
+> A little after the declaration of the spec of the vector in
+> A.18.2, the API
+> says:
+>
+>  * it inserts or deletes elements of V, that is, it calls the Insert,
+>    Insert_Space, Clear, Delete, Delete_Last, or Set_Length
+> procedures with V
+>    as a parameter; or
+>
+> MJH:
+>
+> Do you want to add Delete_First to this list?
+>
+> ENDMJH.
+
+No, Delete_Last was included by mistake. Since Delete_Last is declared in
+terms of Clear and Delete, it is covered by the list already. (That's not
+true for Lists, for instance, which is probably why the error happened.)
+
+I note that it is not included in the Amendment or AARM text, so it probably
+was noticed and incompletely fixed.
+
+> And a little after that, then API says:
+>
+> Some operations are assumed to not change elements. For such an
+> operation, a
+> subprogram is said to *tamper with elements* of a vector object V if:
+>
+>    * it tampers with cursors of V; or
+>    * it modifies one or more elements of V, that is, it calls the
+>      Replace_Element, Update_Element, or Swap procedures or an
+>      instance of Generic_Sort with V as a parameter.
+>
+>    AARM Note:
+>    Swap and Generic_Sort copy elements rather than reordering them, so
+>    they can be allowed for Iterate.
+>
+> MJH:
+>
+> I don't see then how you can implement a tamper-resistent vector using a
+> single internal counter (see the AARM note the follows the description of
+> the Iterate operation).  You're saying that calling Generic_Sort is allowed
+> during Iterate, but not allowed during (say) Query_Element.  So how can you
+> use a single counter to handle both cases?  (But maybe there is a way that I
+> just haven't figured out.)
+
+It's clear that there has to be separate indicators for "tamper with
+cursors" and "tamper with elements". They were split at the last moment to
+fix a serious bug, so it's possible that not all of the notes were updated.
+But I can't find anything that says you can implement both with a single
+counter...
+
+> Perhaps it is the case that you can't call Swap during Iterate.  I think
+> it's true that in our model, a cursor designates an element.  If you sort
+> during Iterate (inside the call to Process.all), then the cursor parameter
+> won't continue to designate the same element after it gets moved into its
+> new sort position (since a cursor is merely an array index).
+>
+> ENDMJH.
+
+It's subtle, but the cursor continues to designate the same element (say the
+10th) when the vector is sorted or elments are swapped. The *contents* of
+the element are changed, but that's because they were copied. So that's OK,
+it won't break the iterator.
+
+However, for a list, the *order* of the cursors is changed for a sort or a
+Swap_Links, which would confuse the iteration. That's why the difference.
+
+We wouldn't have to be that subtle, and just disallow Swap and sorting all
+of the time. But we figured more capability was better.
+
+> procedure Set_Length (Container : in out Vector;
+>                       Length    : in     Count_Type);
+>
+> MJH:
+>
+> If Set_Length is called by Process.all during Iterate, and the
+> requested length is the same as the current length, then is this an
+> error?  Or is the implementation still required to raise PE?
+>
+> ENDMJH.
+
+It's still an error. It gets much too messy and error prone to make it
+depend on the exact values of the parameters and the state of the Vector.
+There are some cases (like this one) where it would be relatively easy to
+allow more, but it doesn't seem worthwhile to do so (why would you want to
+Set_Length to the same length, when you couldn't set it to any other
+length?)
+
+> procedure Delete (Container : in out Vector;
+>                   Index     : in     Extended_Index;
+>                   Count     : in     Count_Type := 1);
+>
+> If Index is not in the range First_Index (Container) .. Last_Index
+(Container),
+> then Constraint_Error is propagated. If Count is 0, Delete has no effect.
+>
+> MJH:
+>
+> I think these two sentences are backwards.  If Count is 0, then it
+> doesn't really matter what value Index has.  (Right?)
+>
+> ENDMJH.
+
+I think one of the reviewers insisted that we check the bounds first.
+Calling Delete with a Count of 0 is rather pathological anyway, so it
+doesn't make much difference in practice. I realize that it is different
+than slices, but I think there is a consensus that the handling of slices in
+Ada is a mistake in this way (because it has a fairly significant impact on
+generated code). Obviously, we're not going to change slices at this late
+date, but there isn't much point in repeating the mistake.
+
+> procedure Delete (Container : in out Vector;
+>                   Position  : in out Cursor;
+>                   Count     : in     Count_Type := 1);
+>
+> If Position equals No_Element, then Constraint_Error is propagated. If Position
+> does not designate an element in Container, then Program_Error is propagated.
+> Otherwise, Delete (Container, To_Index (Position), Count) is called.
+>
+> MJH:
+>
+> Is that first sentence true even when Count = 0?  Shouldn't Count=0 be a
+> no-op?
+>
+> ENDMJH.
+
+Same comments as above.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, March 25, 2005  9:23 AM
+
+>>I think these two sentences are backwards.  If Count is 0, then it
+>>doesn't really matter what value Index has.  (Right?)
+> 
+> I think one of the reviewers insisted that we check the bounds first.
+> Calling Delete with a Count of 0 is rather pathological anyway, so it
+> doesn't make much difference in practice. I realize that it is different
+> than slices, but I think there is a consensus that the handling of slices in
+> Ada is a mistake in this way (because it has a fairly significant impact on
+> generated code). Obviously, we're not going to change slices at this late
+> date, but there isn't much point in repeating the mistake.
+
+But this does mean that you can't delete 0 elements from an empty 
+vector.  Delete will raise CE because the index check will always fail.
+
+That is just a limiting case of deleting 0 elements off the end of a 
+vector, empty or not.
+
+You're sure this is what you want?
+
+One of the nice things about Ada arrays is that you don't have to think 
+too hard about 0-length arrays, since the language always does the right 
+thing.
+
+You shouldn't have to worry about calling an operation for which the 
+Count parameter has the value 0.  The language should do the right thing 
+(that is, do nothing).
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, March 25, 2005  7:03 PM
+
+The index-based Delete operation is declared this way:
+
+   procedure Delete (Container : in out Vector;
+                     Index     : in     Extended_Index;
+                     Count     : in     Count_Type := 1);
+
+Why does parameter Index have subtype Extended_Index?  That subtype includes
+the values Index_Type'First - 1 and Index_Type'Last + 1, yet both of these
+values will fail the index check that happens as the first processing step.
+
+The subtype Extended_Index appears to be vestigial.  It would only make
+sense if the check for Count=0 happens prior to the index check.  Since the
+semantics were changed, and the index check now happens first, you might as
+well strengthen the precondition and declare parameter Index with (sub)type
+Index_Type.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Sunday, March 27, 2005 10:52 PM
+
+> But this does mean that you can't delete 0 elements from an empty 
+> vector.  Delete will raise CE because the index check will 
+> always fail.
+
+The description of Delete_First says:
+
+START OF QUOTE:
+
+procedure Delete_First (Container : in out Vector;
+                        Count     : in     Count_Type := 1);
+
+    {AI95-00302-03} Equivalent to Delete (Container, Index_Type'First,
+                    Count).
+
+END OF QUOTE.
+
+
+What is the behavior when the vector is empty?  Does Delete_First raise CE
+or not?
+
+The description of Delete says:
+
+START OF QUOTE:
+
+procedure Delete (Container : in out Vector;
+                  Index     : in     Extended_Index;
+                  Count     : in     Count_Type := 1);
+
+    {AI95-00302-03} If Index is not in the range First_Index (Container)
+     .. Last_Index (Container), then Constraint_Error is propagated...
+
+END OF QUOTE.
+
+For an empty vector, Index_Type'First is not in the indicated range, so I
+guess the answer is that CE is raised.  However, the description of
+Delete_Last says:
+
+START OF QUOTE:
+
+procedure Delete_Last (Container : in out Vector;
+                       Count     : in     Count_Type := 1);
+
+    {AI95-00302-03} If Length (Container) <= Count then Delete_Last is
+        equivalent to Clear (Container)...
+
+END OF QUOTE.
+
+For an empty vector, Delete_Last does nothing.  This would mean that
+Delete_First and Delete_Last behave differently for an empty vector.  Was
+this the intent?
+
+****************************************************************
+
+From: Matt Heaney
+Sent: Tuesday, March 29, 2005 10:05 PM
+
+> > Why, for example, is inserting 0 elements at the end of a
+> > vector a no-op, while deleting 0 elements from the end is an error?
+> 
+> That's a different issues, and I agree this seems inconsistent.
+
+The guiding principle was always "inserting or deleting 0 items is never an
+error."  The old rule handles the corner case of inserting or deleting 0
+items in a vector that is full (such that Last_Index (V) = Index_Type'Last).
+
+The new rule will raise CE, since the API specifies that the index check
+must be performed prior to the count=0 check.  But this doesn't make any
+sense, since count=0 doesn't change the state of the container.  
+
+The purpose of exceptions is to prevent damage to the container, or to
+indicate that the postcondition can not be satisfied.  The new rule is
+wrong, since no damage can occur, and the postcondition is satisfied, when
+count=0.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Wednesday, March 30, 2005 1:57 AM
+
+> > That's a different issues, and I agree this seems inconsistent.
+> 
+> The guiding principle was always "inserting or deleting 0 
+> items is never an error."  The old rule handles the corner 
+> case of inserting or deleting 0 items in a vector that is 
+> full (such that Last_Index (V) = Index_Type'Last).
+> 
+> The new rule will raise CE, since the API specifies that the 
+> index check must be performed prior to the count=0 check.  
+> But this doesn't make any sense, since count=0 doesn't change 
+> the state of the container.  
+> 
+> The purpose of exceptions is to prevent damage to the 
+> container, or to indicate that the postcondition can not be 
+> satisfied.  The new rule is wrong, since no damage can occur, 
+> and the postcondition is satisfied, when count=0.
+
+I am worried by the inconsistency that you pointed out, but on the other
+hand I am unconvinced by your argument.  One purpose of exceptions is to
+preserve the integrity of the container.  But another, equally important,
+purpose is to ensure that usages that are so outlandish that they probably
+indicate bugs are flagged.
+
+If I have a vector with index range 1..10, and I am deleting elements at
+position 20, surely something is fishy.  Now you are telling me that if
+the number of elements that I am deleting happens to be 0, it's OK to hide
+the fishiness.  
+That bothers me.  I see the situation (Position => 20, Count => 0) to be a
+special case of (Position => 20, Count => N), rather than (Position => N,
+Count => 0).
+
+****************************************************************
+
+From: Matt Heaney
+Sent: Wednesday, March 30, 2005 7:57 AM
+
+For a vector with index range 1..10, we're really only talking about
+deleting 0 elements at position 11; that is, the value Last_Index (V) + 1.
+This is the same range we allow for Insert.
+
+****************************************************************
+
+From: Matt Heaney
+Sent: Thursday, April 1, 2005 11:40 PM
+
+Actually, we could liberalize the rule for the index-based delete such that
+we allow the Index parameter to have the value Last_Index (V) + 1, no matter
+what the value of the Count parameter.  With these semantics we wouldn't
+have to have a special case for Count=0.
+
+The reason is that Delete always computes the minimum of:
+
+  N1 = Count
+  N2 = Last_Index (V) - Index + 1.
+
+If Index = Last_Index (V) + 1, then N2 has the value 0.  This is equivalent
+to our special case, which says Count=0 does nothing.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 24, 2005  6:37 PM
+
+...
+> It's relatively cheap to check for changes of cardinality during
+> iteration, using the counter as described in the AARM Note near the
+> description of Iterate.
+
+Right.
+
+> However, the API fragment I have cited above wants to make a stronger
+> check: that a specific element isn't updated while Query_Elem is in
+> progress.  How can you make this check without having a separate counter
+> for each vector element?
+
+The *problem* is with specific elements; but the check isn't phrased that
+way.
+
+> What is the exact intent of the "tampers with elements" check?  To
+> monitor whether any element is being manipulated, or to monitor specific
+> elements?
+
+It's as written.
+
+> If the former (any element), then you do intend to restrict the user's
+> ability to manipulate other elements while a query of an element is in
+> progress?  If so, then it would appear that description of the
+> implementation of the check (using a single internal counter) is
+> incorrect, since two internal counters are necessary.
+
+There is clearly one counter for each "tamper with" check. Actually, the
+*tamper with elements* only needs a single bit, because it can't be
+recursive, and there isn't any requirement to worry about multiple tasks.
+
+> If the latter (specific elements), then how can you monitor specific
+> elements without using a per-element counter?
+
+You can't, but that isn't the intent.
+
+> You have the AARM Note cited above that gives a rationale for the
+> tampers-with-element check, but do we really want to do this?
+
+Yes. It was what was agreed to in Atlanta. I was still concerned that this
+was too limiting, so I wrote up some examples of what would be disallowed
+and presented them in Paris. (I was in favor of a per-element check.) The
+group was very firm that they wanted to stick to the overall check. Since
+it's already been explicitly discussed twice, an attempt to bring it up
+again would be way out of bounds.
+
+> If a user is querying an element, and then manipulates that same element by
+> calling other operations inside Process.all, then isn't this just a case
+> of aliasing?  Why is this the container's problem?
+
+There are two problems with this:
+  (1) Since we're not specifying the implementation of the container, we
+can't lean on the existing language rules here. We have to state in some
+fashion what happens. So it certainly is the containers problem. One
+possibility considered was to allow it to be aliased, but that doesn't
+always work. Which brings us to
+  (2) The container might allocate different memory for the element if it is
+modified. Depending on the implementation, that could happen for pretty much
+any composite type. (Not to mention reallocation of vectors.) But the fact
+that we're defining indefinite containers means that it is pretty much
+required in some cases (say, if a different lengthed string was inserted).
+That would leave the parameter to Process.all pointing to deallocated memory
+(presuming it was passed by reference, which is most likely, and what we
+generally want in this case anyway) -- which is the worst kind of
+erroneousness.
+
+I think there was a fairly strong feeling that programming with the
+containers should be as safe (and preferably safer) than programming with
+"bare" access types and the like. One of the big advantages of using a
+predefined container is that it can make the kinds of checks that you would
+never bother to program yourself. (That's one reason why C++ programs seem
+so enamored of Std::Vector -- it makes the checks that they would never
+write themselves.)
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Thursday, March 24, 2005  9:21 PM
+
+> There is clearly one counter for each "tamper with" check. 
+> Actually, the *tamper with elements* only needs a single bit, 
+> because it can't be recursive, and there isn't any 
+> requirement to worry about multiple tasks.
+
+Now I'm really confused.  Here is a list example from the !examples section:
+
+START OF QUOTE:
+
+For the definite form (the case here), this will make a copy of the
+element in order to perform the swap. However, we would prefer not to
+make a copy of this element, which is a list and hence potentially large
+(or otherwise expensive to copy). To avoid making a copy, we can use
+Move and nested processing routines:
+
+  procedure Swap
+    (V    : in out Vector_Of_Lists.Vector;
+     I, J : in     Extended_Index) is
+
+     procedure Process_I (IE : in out List) is
+
+        procedure Process_J (JE : in out List) is
+           IE_Temp : List;
+        begin
+           Move (Target => IE_Temp, Source => IE);
+           Move (Target => IE, Source => JE);
+           Move (Target => JE, Source => IE_Temp);
+        end;
+
+     begin
+        Update_Element (V, Index => J, Process => Process_J'Access);
+     end;
+
+  begin
+     Update_Element (V, Index => I, Process => Process_I'Access);
+  end Swap;
+
+END OF QUOTE.
+
+
+Is this example legal or illegal?  Does this raise PE or not? 
+
+This certainly looks like a kind of recursion, so I don't understand how you
+can implement this using "a single bit."
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Thursday, March 24, 2005  10:06 PM
+
+> It's clear that there has to be separate indicators for 
+> "tamper with cursors" and "tamper with elements". They were 
+> split at the last moment to fix a serious bug, so it's 
+> possible that not all of the notes were updated. 
+
+To what "serious bug" are you referring?
+
+> But I can't 
+> find anything that says you can implement both with a single 
+> counter...
+
+The AARM Note that follows the description of Iterate says:
+
+START OF QUOTE:
+
+The check is easy to implement: each container needs a counter. The counter
+is incremented when Iterate is called, and decremented when Iterate completes.
+If the counter is nonzero when an operation that inserts or deletes is called,
+Finalize is called, or one of the other operations in the list occurs,
+Program_Error is raised.
+
+END OF QUOTE.
+
+This wording makes it seem as if only a single counter is necessary.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 24, 2005  10:41 PM
+
+...
+> Now I'm really confused.  Here is a list example from the
+> !examples section:
+...
+> Is this example legal or illegal?
+
+It's legal, of course (in that you can compile it, which is the meaning of
+"legal" in the Standard).
+
+> Does this raise PE or not?
+
+Yes, it does raise PE, because the inner Update_Element certainly "tampers
+with elements" (read the definition carefully).
+
+This is one of the examples I showed at Paris (although I didn't realize it
+was in the AI, that will have to be fixed!).
+
+> This certainly looks like a kind of recursion, so I don't
+> understand how you
+> can implement this using "a single bit."
+
+The example will raise Program_Error, so a single bit is sufficient.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 24, 2005 10:45 PM
+
+> > It's clear that there has to be separate indicators for
+> > "tamper with cursors" and "tamper with elements". They were
+> > split at the last moment to fix a serious bug, so it's
+> > possible that not all of the notes were updated.
+>
+> To what "serious bug" are you referring?
+
+The erroneousness I mentioned in an earlier message today. The whole point
+of the check for Update_Element and Query_Element was to eliminate that
+problem, and we'd missed the most likely cause.
+
+...
+> This wording makes it seem as if only a single counter is necessary.
+
+Sure, you only need a single counter to implement the check for Iterate. Why
+would you think this would be talking about some other, unrelated check??
+
+You need an extra bit to implement the check for Update_Element and
+Query_Element; I don't think that there is any note discussing that, but it
+seems obvious (since recursion is not allowed).
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Thursday, March 24, 2005  10:57 PM
+
+> Sure, you only need a single counter to implement the check 
+> for Iterate. Why would you think this would be talking about 
+> some other, unrelated check??
+
+Because it says "each container needs a counter." 
+
+
+> You need an extra bit to implement the check for 
+> Update_Element and Query_Element; I don't think that there is 
+> any note discussing that, but it seems obvious (since 
+> recursion is not allowed).
+
+So you don't even allow Query_Element to recurse?  What is the harm in
+allowing nested invocations of Query_Element (as in the example from my
+previous example)?
+
+How does a developer get a constant view of two elements simultaneously?
+
+In one of my examples, I compare a pair of elements in a vector like this:
+
+function Is_Equal (I, J : Positive) return Boolean is
+   Result : Boolean;
+
+   procedure Process_I (IE : in Pair_Type) is
+      procedure Process_J (JE : in Pair_Type) is
+      begin
+         Result := Equal_Case_Insensitive (IE.Sorted, JE.Sorted);
+      end;
+   begin
+      Query_Element (V, J, Process_J'Access);
+   end;
+begin
+   Query_Element (V, I, Process_I'Access);
+   return Result;
+end Is_Equal;
+
+
+Are you saying this will raise PE?
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 24, 2005 11:19 PM
+
+Matthew Heaney wrote:
+
+> > Sure, you only need a single counter to implement the check
+> > for Iterate. Why would you think this would be talking about
+> > some other, unrelated check??
+>
+> Because it says "each container needs a counter."
+
+Of course it needs a counter. It needs lots of other stuff, too (length,
+pointer to elements, etc.), but we're not talking about those things here.
+This doesn't say that it *only* needs a counter to implement every check in
+the universe!
+
+> > You need an extra bit to implement the check for
+> > Update_Element and Query_Element; I don't think that there is
+> > any note discussing that, but it seems obvious (since
+> > recursion is not allowed).
+>
+> So you don't even allow Query_Element to recurse?  What is the harm in
+> allowing nested invocations of Query_Element (as in the example from my
+> previous example)?
+
+What gave you that idea? The check is defined to be "tamper with elements";
+read the wording if you want to know *exactly* what is required.
+
+Query_Element doesn't "tamper with elements". So it of course can be
+recursively called. But it doesn't participate in the check, it just needs
+the check made. So I don't see the issue.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Thursday, March 24, 2005 11:44 PM
+
+> Query_Element doesn't "tamper with elements". So it of course 
+> can be recursively called. But it doesn't participate in the 
+> check, it just needs the check made. So I don't see the issue.
+
+Well, I still don't understand the RM.  How you can you implement nested
+calls to Query_Element without using a counter?
+
+I have repeated my example from my last message, and marked the calls to
+Query_Element "call #1" and "call #2".
+
+You're telling me that invocation must raise PE if it tampers with elements.
+Fine.  That means there needs to be some state to indicate that a call to
+Query_Element is in progress, and that state is checked by an operation that
+tampers with elements.
+
+So QE sets the bit when called at point #1.  The invocation of QE at point
+#2 also sets the bit.  When QE #2 finishes executing, it sets the bit to
+false.  But that wipes out the indication that QE #1 is still executing.
+Right?
+
+
+function Is_Equal (I, J : Positive) return Boolean is
+   Result : Boolean;
+
+   procedure Process_I (IE : in Pair_Type) is
+      procedure Process_J (JE : in Pair_Type) is
+      begin
+         Result := Equal_Case_Insensitive (IE.Sorted, JE.Sorted);
+      end;
+   begin
+      Query_Element (V, J, Process_J'Access);  --call #2
+   end;
+begin
+   Query_Element (V, I, Process_I'Access);  --call #1
+   return Result;
+end Is_Equal;
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, March 25, 2005  12:03 AM
+
+...
+> So QE sets the bit when called at point #1.  The invocation of QE at point
+> #2 also sets the bit.  When QE #2 finishes executing, it sets the bit to
+> false.  But that wipes out the indication that QE #1 is still executing.
+> Right?
+
+Yes it would. But you could save the previous state of the bit in the local
+data for each call to QE, and restore that on exit. That would eliminate the
+need for a counter. (It seems that would work for Iterate, as well. Or maybe
+it's just getting too late to reason. :-)
+
+Of course, worrying about one or two bytes per container seems like overkill
+in any case.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, March 25, 2005  2:56 PM
+
+Does the following program raise PE or not?
+
+V : Vector;
+...
+procedure Op (I : IT) is
+    procedure Process_Update (U : in out ET) is
+       procedure Process_Query (Q : in ET) is
+       begin
+          U := U + 1;
+       end;
+    begin
+       Query_Element (V, I, Process_Query'Access);
+    end;
+begin
+    Update_Element (V, I, Process_Update'Access);
+end;
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, March 25, 2005  7:12 PM
+
+No; Query_Element doesn't "tamper with elements". As I said before, read the
+wording carefully to determine what happens; don't ask me -- I make
+mistakes! (If you're still confused after reading the wording, of course,
+please ask.)
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, March 25, 2005  9:09 PM
+
+> No; Query_Element doesn't "tamper with elements". As I said 
+> before, read the wording carefully to determine what happens; 
+> don't ask me -- I make mistakes! (If you're still confused 
+> after reading the wording, of course, please ask.)
+
+I think the wording is wrong.  The text that follows the declaration of the
+spec says:
+
+START OF QUOTE:
+
+Some operations are assumed to not change elements. For such an operation, a
+subprogram is said to *tamper with elements* of a vector object V if:
+
+   * it tampers with cursors of V; or
+   * it modifies one or more elements of V, that is, it calls the
+     Replace_Element, Update_Element, or Swap procedures or an
+     instance of Generic_Sort with V as a parameter.
+
+END OF QUOTE.
+
+That second bullet says that Update_Element tampers with elements.  This
+isn't quite correct.  It's the Process.all parameter of Update_Element that
+can tamper with elements.  Any tampering is a side-effect of the call to
+Update_Element, rather than the call itself.
+
+The reason this makes a difference is what I said in my last email message,
+since changing the order of nested calls to Query_Element and Update_Element
+can have different behavior.  A strict reading of the second bullet above
+means that calling Update_Element during Query_Element raises PE, while
+calling Query_Element during Update_Element does not.
+
+The description for Update_Element is correct:
+
+START OF QUOTE:
+
+procedure Update_Element
+  (Container : in Vector;
+   Index     : in Index_Type;
+   Process   : not null access procedure (Element : in out Element_Type));
+
+...Program_Error is propagated if Process.all tampers with the elements of
+Container. Any exception raised by Process.all is propagated.
+
+END OF QUOTE.
+
+
+This means that merely calling Update_Element from within Update_Element
+should *not* in itself raise PE.  The exception should only occur if the
+inner Update_Element tampers with elements from with its Process.all.  That
+Process.all of the outer Update_Element merely calls Update_Element should
+not raise PE.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, March 25, 2005  9:34 PM
+
+> This is one of the examples I showed at Paris (although I 
+> didn't realize it was in the AI, that will have to be fixed!).
+
+I believe this statement is incorrect.  The nested call to Update_Element
+should not raise PE.  
+
+There is a distinction between "tampering" with an element and merely
+"modifying" an element.
+
+I suggest defining "tampering" to mean a call to a container operation that
+modifies the container element.  For example, Replace_Element is a vector
+operation that "tampers" with an element.
+
+By "modifying" I mean some kind of direct manipulation of the Element
+parameter from inside the call to Process.all.
+
+That would explain why the nested call to Update_Element from the list
+!example should not raise PE, since it merely "modifies" the vector element
+directly via the Process.all parameter.  It does not "tamper" with the
+element and hence does not break the vector.
+
+It would be a different matter if the example were to call Replace_Element.
+In the indefinite vector case, this would deallocate the existing element,
+which would be disaster since Process.all parameter is an alias of that
+object.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, March 25, 2005  7:38 PM
+
+> No; Query_Element doesn't "tamper with elements". As I said 
+> before, read the wording carefully to determine what happens; 
+> don't ask me -- I make mistakes! (If you're still confused 
+> after reading the wording, of course, please ask.)
+
+I have reproduced the example from my last post, with one difference: I have
+reversed the order of calls to Update_Element and Query_Element.  The nested
+call to Update_Element "tampers with an element," and therefore it raises
+PE.
+
+My question concerns the rationale for the behavior.  These programs do
+exactly the same thing, yet they exhibit two different behaviors.  Why the
+difference?
+
+V : Vector;
+...
+procedure Op (I : IT) is
+    procedure Process_Query (Q : in ET) is
+       procedure Process_Update (U : in out ET) is
+       begin
+          U := U + 1;
+       end;
+    begin
+       Update_Element (V, I, Process_Update'Access);
+    end;
+begin
+    Query_Element (V, I, Process_Query'Access);
+end;
+
+> > procedure Op (I : IT) is
+> >     procedure Process_Update (U : in out ET) is
+> >        procedure Process_Query (Q : in ET) is
+> >        begin
+> >           U := U + 1;
+> >        end;
+> >     begin
+> >        Query_Element (V, I, Process_Query'Access);
+> >     end;
+> > begin
+> >     Update_Element (V, I, Process_Update'Access);
+> > end;
+
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, March 25, 2005 11:28 PM
+
+Your analysis is interesting, but it wasn't the intended design. That was
+that Replace_Element and Update_Element are interchangable. That is, the
+same thing happens when you call either of them. The intent is that
+Update_Element do nothing internally other than update the element; nested
+calls on the same container are bad (and you couldn't do them using
+Replace_Element).
+
+If you were to allow Update_Element as you suggest, you'd still have issues
+of data loss and the bounded error of "multiple access paths" in the case
+when an inner Update_Element was called on the same element. I think you're
+arguing that that should be programmer's problem. My personal feeling is
+that a library that allows such things is seriously flawed.
+
+A per-element check would clearly be better in this case, but the majority
+think that that is too much overhead. (I'd also prefer a dangling cursor
+check in the case where the container hasn't been finalized, but that is
+considered too much overhead as well.)
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Saturday, March 26, 2005  12:21 AM
+
+> Your analysis is interesting, but it wasn't the intended 
+> design. That was that Replace_Element and Update_Element are 
+> interchangable. 
+
+But the API already treats them differently:
+
+START OF QUOTE:
+
+procedure Update_Element
+  (Container : in Vector;
+   Index     : in Index_Type;
+   Process   : not null access procedure (Element : in out Element_Type));
+...
+AARM Note: Since reading an empty element is a bounded error, attempting to
+use this procedure to replace empty elements may fail. Use Replace_Element
+to do that reliably.
+
+END OF QUOTE.
+
+
+> That is, the same thing happens when you call 
+> either of them. The intent is that Update_Element do nothing 
+> internally other than update the element; nested calls on the 
+> same container are bad (and you couldn't do them using 
+> Replace_Element).
+
+The thing that is bad is that an object is aliased, then destroyed, and then
+referred to by the alias.
+
+"Nested calls on the same container" by itself isn't bad.
+
+The problem with the current semantics (besides being too conservative) is
+that the consequences are surprising.  I gave an example of how merely
+reversing nested calls to Query_Elem and Update_Elem can raise PE; this
+doesn't make any sense.
+
+
+> If you were to allow Update_Element as you suggest, you'd 
+> still have issues of data loss and the bounded error of 
+> "multiple access paths" in the case when an inner 
+> Update_Element was called on the same element. I think you're 
+> arguing that that should be programmer's problem. 
+
+Yes.  But this happens not simply because you're using a container.  It
+happens because of aliasing during nested subprogram calls.
+
+> My personal feeling is that a library that allows such things is seriously flawed.
+
+This is a consequence of subprogram nesting and aliasing; it is a feature of
+the language.  It is not a library issue.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Saturday, March 26, 2005  1:08 AM
+
+> ...
+> AARM Note: Since reading an empty element is a bounded error, attempting to
+> use this procedure to replace empty elements may fail. Use Replace_Element
+> to do that reliably.
+>
+> END OF QUOTE.
+
+True, but (a) that's a pathology; and (b) it can't be helped (Update_Element
+has to read the element to pass it to "Process").
+
+...
+> "Nested calls on the same container" by itself isn't bad.
+
+We're not talking about any old "nested calls". We're talking about calls
+that happen from inside of a call-back -- that is, during the operation of
+some other operations.
+
+And those are always bad. That's because they constrain how the outer
+operation can be implemented.
+
+Moreover, the only intent here is to provide a more efficient way to update
+an element. Not some general way to do nested operations.
+
+Now, we decided to allow read operations on the container, under the
+assumption that these can be implemented harmlessly. We decided not to allow
+write operations on any part of the container.
+
+> The problem with the current semantics (besides being too conservative) is
+> that the consequences are surprising.  I gave an example of how merely
+> reversing nested calls to Query_Elem and Update_Elem can raise PE; this
+> doesn't make any sense.
+
+There is no intent to allow any sort of writes to the container inside of
+Process. So it shouldn't be surprising that when you do so, you get an
+exception.
+
+Order often matters in programming. There should be nothing surprising about
+that.
+  A := B; is not the same as B := A; and that is essentially what you are
+writing here.
+
+> > If you were to allow Update_Element as you suggest, you'd
+> > still have issues of data loss and the bounded error of
+> > "multiple access paths" in the case when an inner
+> > Update_Element was called on the same element. I think you're
+> > arguing that that should be programmer's problem.
+>
+> Yes.  But this happens not simply because you're using a container.  It
+> happens because of aliasing during nested subprogram calls.
+
+No, it happens because the container has call-back routines. And those the
+calls that actually make the aliasing are not anywhere in the source code to
+the (users) program.
+
+We have to protect the user and (especially) the container for abuse of
+those user-written call-backs. We can't assume the user is on good behavior
+or understands the consequences of their actions. (Every programmer makes
+mistakes.)
+
+> > My personal feeling is that a library that allows such things is seriously
+> > flawed.
+>
+> This is a consequence of subprogram nesting and aliasing; it is a feature of
+> the language.  It is not a library issue.
+
+Of course it is a library issue, because the library allows it to occur in
+the first place. The existence of the call-backs in the library causes the
+trouble that we have to fix. If there were no call-backs, this particular
+issue would not exist.
+
+(Of course, then you'd want reference-returning functions, which are far
+worse in terms of safety. Their use is essentially equivalent to saying "any
+use of this container is erroneous", because there would be no way of
+knowing what operation on the container changed the memory that is
+referenced.)
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Saturday, March 26, 2005  4:19 AM
+
+> Of course it is a library issue, because the library allows 
+> it to occur in the first place. The existence of the 
+> call-backs in the library causes the trouble that we have to 
+> fix. If there were no call-backs, this particular issue would 
+> not exist.
+
+For the record, I agree with everything that Randy said in this and other
+messages.
+
+Matt, you would have to present a convincing example where some legitimate
+usage of the containers is prevented by the current semantics.  So far
+your examples have been totally pathological, so it's hard to get excited
+about them.
+
+Also remember that we decided a while ago against element-level locking.
+While it is true that not having element-level locking does prevent some
+legitimate uses of the containers, the feeling was that the cost was too
+high for a relatively minor annoyance.  This is of course a trade-off, but
+so far you haven't presented any argument that would require us to
+reconsider this decision.
+
+Finally, keep in mind that at this point any proposal that would weaken
+the safety of the containers is a no-no, since the ARG has consistently
+decided on dozens of issues that safety was of prime importance.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Saturday, March 26, 2005  9:33 AM
+
+> So far your examples have been totally 
+> pathological, so it's hard to get excited about them.
+
+"Pathological" is your pejorative term.  I just call the examples I have
+shown "corner cases."  
+
+Why, for example, is inserting 0 elements at the end of a vector a no-op,
+while deleting 0 elements from the end is an error?
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, March 29, 2005  2:58 AM
+
+> "Pathological" is your pejorative term.  I just call the 
+> examples I have shown "corner cases."  
+
+I was thinking of your example with Query_Element/Update_Element.  It
+didn't do anything useful, and it also included rather mysterious
+side-effects.  Your argument would be much more convincing if you
+exhibited a code fragment that did something simple.
+
+> Why, for example, is inserting 0 elements at the end of a 
+> vector a no-op, while deleting 0 elements from the end is an error?
+
+That's a different issues, and I agree this seems inconsistent.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Tuesday, March 29, 2005 10:05 PM
+
+> I was thinking of your example with 
+> Query_Element/Update_Element.  It didn't do anything useful, 
+> and it also included rather mysterious side-effects.  
+
+But that was my point.  The semantics of Update_Element were defined such
+that it "tampers with elements," and the reason they were defined this way
+was to prevent accidental aliasing and other Bad Things.
+
+However, the semantics as specified don't solve the problem you're trying to
+solve, since the aliasing can happen if you call Query_Element and
+Update_Element in the opposite order, and there is no error.
+
+
+> Your 
+> argument would be much more convincing if you exhibited a 
+> code fragment that did something simple.
+
+Well, I thought my original vector !example demonstrated something useful;
+that is, using nested calls to Update_Element to get a pair of elements in
+scope, each with a variable view.  (This was a vector of lists, and the
+example swapped the list elements.)
+
+There have been lots of times when I've used a pair of non-const iterators
+to manipulate two container elements:
+
+  typedef container_t::iterator iter_t;
+
+  iter_t curr = container.begin();
+  const iter_t end = container.end();
+
+  while (curr != end)
+  {
+     iter_t next = curr;
+     ++next;
+
+     if (next == end)
+        break;
+
+     //now do something with curr and next,
+     //each of which designates a non-const elem
+
+     //now maybe move next ahead a few more positions
+
+     //and finally:
+     curr = next;
+  }
+
+
+I often do this when using a list as a queue, and use an iterator to
+navigate forward a few elements to inspect what's ahead in the queue.  (In
+my case, I usually looking for a keyframe from a live capture process.)
+
+But you're telling me I can't do this.  I'm not allowed to have more than
+one element with a variable view in the same scope.  Actually, I'm not even
+allowed to have a variable view in a more nested scope then a constant view.
+(But the opposite *is* allowed.  Go figure.)
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Wednesday, March 30, 2005  1:46 AM
+
+OK, you don't like the semantics presented in the AI, fair enough.  But
+what exactly are you proposing?  I must say that I don't understand what
+you want.  If you want element-level locking, then you'll have to convince
+the rest of us that the cost is worth the extra flexibility (after all,
+you have been very vocal about minimizing the overhead of the containers).
+If you want some other form of locking (maybe with different forms of
+"tampering") you'll have to spell out the rules and to demonstrate that
+they work even in presence of aliasing, funny parameter passing, etc.  If
+you want to just make the container unsafe, well, forget it.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, March 25, 2005  8:01 AM
+
+> OK, you don't like the semantics presented in the AI, fair 
+> enough.  But what exactly are you proposing?  I must say that 
+> I don't understand what you want.  If you want element-level 
+> locking, then you'll have to convince the rest of us that the 
+> cost is worth the extra flexibility (after all, you have been 
+> very vocal about minimizing the overhead of the containers). 
+> If you want some other form of locking (maybe with different forms of
+> "tampering") you'll have to spell out the rules and to 
+> demonstrate that they work even in presence of aliasing, 
+> funny parameter passing, etc.  If you want to just make the 
+> container unsafe, well, forget it.
+
+The rules you have right now have all the "problems" you describe.  You
+still haven't explained why calling Query_Element from Update_Element is
+safe (because there's no error), but calling Update_Element from
+Query_Element is unsafe (because there's an exception).
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, March 25, 2005  4:31 PM
+
+> The rules you have right now have all the "problems" you describe.  You
+> still haven't explained why calling Query_Element from Update_Element is
+> safe (because there's no error), but calling Update_Element from
+> Query_Element is unsafe (because there's an exception).
+
+Why would calling Query_Element from Update_Element be unsafe? You can't
+modify the argument of Query_Element, or do anything bad to the container
+from it. So how could there be a problem?
+
+(If there is a way for there to be a problem, then clearly Query_Element
+should be prohibited inside of Update_Element. There is no intent to allow
+any changes to the container from inside of one of these call-backs; if
+there is any covert channel, it should be plugged.)
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+> The rules you have right now have all the "problems" you describe.  You
+> still haven't explained why calling Query_Element from Update_Element is
+> safe (because there's no error), but calling Update_Element from
+> Query_Element is unsafe (because there's an exception).
+
+Why would calling Query_Element from Update_Element be unsafe? You can't
+modify the argument of Query_Element, or do anything bad to the container
+from it. So how could there be a problem?
+
+(If there is a way for there to be a problem, then clearly Query_Element
+should be prohibited inside of Update_Element. There is no intent to allow
+any changes to the container from inside of one of these call-backs; if
+there is any covert channel, it should be plugged.)
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, March 25, 2005  5:15 PM
+
+Randy Brukardt wrote:
+> 
+> Why would calling Query_Element from Update_Element be unsafe?
+
+That's the wrong question.  The question should be, Would it be unsafe 
+to allow an element to be updated, if there are multiple access paths to 
+the element?
+
+If the answer is yes, then it shouldn't matter how multiple access paths 
+to an element are created.
+
+
+ >You can't modify the argument of Query_Element, or do anything bad
+ >to the container from it. So how could there be a problem?
+
+Correct, you can't modify the argument of Query_Element.  However, you 
+can modify the argument of Update_Element, if it's in an outer scope:
+
+procedure Op
+   (V : Vector;
+    I : Index_Subtype) is
+
+    procedure Process_Update (X : in out ET) is
+      procedure Process_Query (Y : in ET) is
+      begin
+         --Y is now an alias of X
+
+         Change_The_Value_Of (X);
+
+         --What value does Y have now?
+
+         Use_The_Value_Of (Y);
+      end;
+    begin
+       Query_Element (V, I, Process_Query'Access);
+    end;
+begin
+    Update_Element (V, I, Process_Update'Access);
+end Op;
+
+
+Both X and Y are access paths to the same element at index I.  One of 
+these names (it doesn't matter which one) denotes a variable view of the 
+element, and this is the situation you deem unsafe.  So why isn't there 
+an exception?
+
+
+> (If there is a way for there to be a problem, then clearly Query_Element
+> should be prohibited inside of Update_Element.
+
+Is the aliasing in the example above a problem?
+
+
+ >There is no intent to allow any changes to the container from inside of
+>one of these call-backs; if there is any covert channel, it should 
+ >be plugged.)
+
+It depends on whether you consider access to a variable view of the 
+element in a more outer scope a "covert channel."
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, March 30, 2005  6:50 AM
+
+Matt Heaney wrote:
+
+> Randy Brukardt wrote:
+> >
+> > Why would calling Query_Element from Update_Element be unsafe?
+>
+> That's the wrong question.
+
+That's the statement you made, I was only asking why you think it is true.
+
+> The question should be, Would it be unsafe
+> to allow an element to be updated, if there are multiple access paths to
+> the element?
+
+That's clearly "Yes". You'll lose the result of any modifications if the
+element type is passed by copy. And that call that causes the multiple
+access paths is not visible in the source code (Update_Element itself
+doesn't include the element in question, only Process has that).
+
+> If the answer is yes, then it shouldn't matter how multiple access paths
+> to an element are created.
+
+I agree, presuming that the multiple access paths are caused by the
+containers library and not by explicit user code. (We're not going to try to
+protect against a programmer writing code that passes an element explicitly
+to some subprogram.)
+
+>  >You can't modify the argument of Query_Element, or do anything bad
+>  >to the container from it. So how could there be a problem?
+>
+> Correct, you can't modify the argument of Query_Element.  However, you
+> can modify the argument of Update_Element, if it's in an outer scope:
+...
+
+> Both X and Y are access paths to the same element at index I.  One of
+> these names (it doesn't matter which one) denotes a variable view of the
+> element, and this is the situation you deem unsafe.  So why isn't there
+> an exception?
+
+Arguably, it's because you've explicitly written an up-level reference, so
+you're explicitly doing something bad. In the other case (with
+Update_Element in the inner case), it's a normal reference, and the trouble
+happens when the Process for Update_Element returns. So there isn't anything
+in the source to show the problem.
+
+But that's rather subtle. It's probably better that the inner call raises an
+exception, because the aliasing is not fully visible in the source code.
+This complicates the situation a bit more, because nesting Query_Element
+inside of another Query_Element certainly is OK.
+
+> > (If there is a way for there to be a problem, then clearly Query_Element
+> > should be prohibited inside of Update_Element.
+>
+> Is the aliasing in the example above a problem?
+
+Hard to say; I never thought of using this much nesting to cause trouble. I
+guess I'd prefer to err on the safe side.
+
+>  >There is no intent to allow any changes to the container from inside of
+> >one of these call-backs; if there is any covert channel, it should
+>  >be plugged.)
+>
+> It depends on whether you consider access to a variable view of the
+> element in a more outer scope a "covert channel."
+
+I don't know; I've changed my mind three times in the last five minutes. :-)
+
+The primary things I was trying to eliminate with this check is (1)
+accessing deallocated memory (for indefinite elements), and (2) unexplained
+loss of modifications (for by-copy elements). The second happens because the
+parameters for by-copy elements are separate objects, and the items are
+copied back when the (invisible) calls to Process return. [Those calls are
+not explicit in the source code, so it is much harder to program around
+them.] And we didn't want rules that depend on the parameter passing
+selected for the element type (as that is implementation-defined in some
+circumstances).
+
+This case really is neither of the above; as the modifications won't be lost
+(Query_Element doesn't copy its parameter back), and (1) can't happen as
+Query_Element doesn't change anything. So it's not critical to check it.
+OTOH, it does seem like a potential error that could be caught.
+
+So I don't know. It doesn't seem important either way.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Saturday, March 26, 2005  8:19 AM
+
+The RM says:
+
+START OF QUOTE:
+
+procedure Move (Target : in out Vector;
+                Source : in out Vector);
+
+If Target denotes the same object as Source, then Move has no effect.
+Otherwise, Move first calls Clear (Target); then, each element from Source
+is removed from Source and inserted into Target in the original order. The
+length of Source is 0 after a successful call to Move.
+
+END OF QUOTE.
+
+Is this correct?  At one point in time it used to be the case that if the
+target weren't empty, then Move would raise CE.  The description above is
+telling me that it's ok for Target to be non-empty.
+
+Did the semantics of Move change, or is the description above incorrect?
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Saturday, March 26, 2005  2:41 PM
+
+The semantics of (some of) the Moves were changed. Some of them were this
+way and some were the other way, and it seemed harmless to let the LHS get
+destroyed automatically in this case. (This wasn't my decision, but I
+eventually was convinced.)
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 5, 2005 12:57 AM
+
+AA-A.TXT says:
+
+92/2  procedure Delete (Container : in out List;
+                        Position  : in out Cursor;
+                        Count     : in     Count_Type := 1);
+
+    93/2  {AI95-00302-03} ... Otherwise Delete
+          removes (from Container) Count elements starting at the element
+          designated by Position (or all of the elements if there are less
+          than Count elements starting at Position).
+
+
+MJH:
+
+I think you want to say "... if there are fewer than Count elements..."
+instead of "... less than Count elements...", since this is a discrete,
+countable quantity.
+
+(For another example, visit your local supermarket and read what the sign
+for the Express lane says.)
+
+ENDMJH.
+
+****************************************************************
+
+From: Adam Beneschan
+Sent: Tuesday, April 5, 2005 11:04 AM
+
+I don't think you want to use that as an example.  They don't have any
+particular reason to get this grammatically correct.  I think the sign
+at my supermarket says 15 ITEMS OR LESS, although I'd have to check
+next time I go.  The sign also says "ALL PAYMENTS ACCEPTED", which is
+probably also incorrect because although they certainly accept ATM and
+credit cards, which they previously did not do in the express lane, I
+doubt that they truly accept all payments---for example, if I
+attempted to pay my bill with Indian rupees or, perhaps, sheep instead
+of with U.S. dollars, I doubt they'd accept it.
+
+However, I believe you're correct that "fewer" should be used here.  I
+don't have a Chicago Manual of Style handy, but a Google search did
+turn this up:
+
+http://www.askoxford.com/asktheexperts/faq/aboutgrammar/lessfewer
+
+****************************************************************
+
+From: Marius Amado Alves
+Sent: Tuesday, April 5, 2005  1:12 PM
+
+It's "fewer."
+
+But what does "all of the elements" mean?
+
+All of the elements in the container?
+
+Certainly not.
+
+However this is the 'face value' of the expression.
+
+So it should say instead "all the elements from the one designated by 
+Position up to the last element," or
+
+Otherwise Delete removes (from Container) N elements starting at the
+element designated by Position, where N is the minimum of Count and the 
+number of elements starting at Position up to the last element.
+
+or something else to the same effect.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Tuesday, April 5, 2005  8:29 PM
+
+AA-A.TXT says:
+
+55/2  {AI95-00302-03} {tamper with cursors (of a list)} Some operations are
+assumed to work on a constant set of elements. For such an operation, a
+subprogram is said to tamper with cursors of a list object L if:
+...
+57/2  it reorders the elements of L, that is, it calls the Splice,
+Swap_Links,
+      or Reverse_List procedures or an instance of Generic_Sort or
+      Generic_Merge with C as a parameter; or
+
+
+139/2 procedure Iterate
+        (Container : in List;
+         Process   : not null access procedure (Position : in Cursor));
+
+    140/2 {AI95-00302-03} ...Program_Error is
+          propagated if Process.all tampers with the cursors of Container.
+
+MJH:
+
+Putting these two paragraphs together means (I think) that if you attempt to
+sort the list during an invocation of Iterate.Process.all, then P_E will get
+raised.
+
+Is this correct?  Does sorting a list during Iterate raise P_E?
+
+I bring this up because sorting during iteration doesn't break iteration (at
+least in a canonical list implementation).  The node you're currently
+visiting might change its relative position in the list, and therefore
+iterate will make more or fewer iterations than it would otherwise, but
+other than that things behave.  The loop eventually terminates, for example.
+
+And what about Query_Element or Update_Element for a list?  Is list sorting
+allowed during an invocation of either of those list operations?
+
+Attempting to sort a vector during a call to vector Query_Elem or
+Update_Elem will raise P_E. (Right?)  This makes sense since a vector swap
+is implemented by copying actual elements, one of which is a parameter of
+the invocation of Process.all.
+
+A list is different, however, since only the relative position of nodes
+change; the list elements are never copied (during a sort).  So the reason
+for prohibiting sorting a vector doesn't semm to apply to a list.
+
+ENDMJH.
+
+****************************************************************
+
+From: Simon J. Wright
+Sent: Wednesday, April 6, 2005  3:11 AM
+
+I would be very upset if I could iterate through a list and see some of the
+elements twice/miss some of the elements.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Wednesday, April 6, 2005  7:08 AM
+
+Fine, then don't sort the list while iterating!
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, April 6, 2005  11:51 AM
+
+Exactly. That's why it raises Program_Error.
+
+Note that if we didn't raise Program_Error, we'd have to explain how it
+works if you sorted during Iterate. It can be done (I had some words about
+an unspecified order), but it's hardly worth it, because sorting breaks the
+invariant of Iterate (which is that each element is visited exactly once).
+
+As far as Query_Element for a list goes, Matt is correct that there isn't an
+actual problem. But we didn't want to have many different checks and
+conditions; two is already plenty confusing. And doing any operation that
+modifies the container from Query_Element is suspicious.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Wednesday, April 6, 2005  7:44 AM
+
+AA-A.TXT says:
+
+100/2 generic
+         with function "<" (Left, Right : Element_Type) return Boolean is
+<>;
+      procedure Generic_Merge (Target  : in out List;
+                               Source  : in out List);
+
+    102/2 Any exception raised during evaluation of "<" is propagated. If
+          Target and Source are not sorted smallest first, then
+Program_Error
+          is propagated. In these cases, Target is left in an unspecified
+          order, but contains the union of the elements that were initially
+in
+          Source and Target; Source is left empty. {unspecified [partial]}
+
+    102.a/2 Ramification: If Program_Error is propagated by Generic_Merge
+          because one of the lists was unsorted, it is possible to recover
+by
+          sorting Target. If Source and Target designate the same object,
+          Generic_Merge is essentially a no-op, but it still has to check
+that
+          the list is sorted.
+
+
+MJH:
+
+These new semantics are grossly inefficient.
+
+In the old semantics, Generic_Merge was only O(n) over the Source.  If you
+have a small source list that you want to merge onto a longer target list,
+then it used to be the case that you stopped your work as soon as the source
+list was exhausted.  (Actually, you stop even sooner if you reach the end of
+the target list, in  which case you simply splice the source onto the end of
+the target.)
+
+But the new semantics don't work that way.  They require that even though
+the source list is exhausted and the actual merge is done, Generic_Merge
+must continue inspecting the target list, simply to determine whether the
+target list is in sort order.
+
+The action of determining whether the target is sorted is only relevant to
+the immediate goal of merging the source list.  Once the source has been
+merged (and this includes the case when target and source denote the same
+list object), then the action of Generic_Merge should immediately terminate.
+
+Furthermore, you require that when you do detect that a list is not in sort
+order, then the source must still be spliced onto the target, prior to
+raising Program_Error.  Is this really the intent?  If you think a list that
+isn't in sort order is bad, then how you do you know that splicing the
+source onto the target in spite of that isn't just making things even worse?
+
+If you want to determine whether the lists are sorted, then fine, you can do
+that inexpensively.  All you need to do is inspect the (next) nearest
+neighbor as you're comparing elements, and then raise PE if Next.Elem <
+Curr.Elem.  But once the source has been merged onto the target however,
+then no further inspection should be required.
+
+ENDMJH.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Wednesday, April 6, 2005  8:21 PM
+
+> Furthermore, you require that when you do detect that a list 
+> is not in sort order, then the source must still be spliced 
+> onto the target, prior to raising Program_Error.  Is this 
+> really the intent?  
+
+It seems odd to require that the source be spliced onto the target, given
+that we raise Program_Error.  That exception is special because it indicates
+that the program is broken.  What would be the point of the splice, if the
+intent of PE is for the developer to repair the program?
+
+> If you want to determine whether the lists are sorted, then 
+> fine, you can do that inexpensively.  All you need to do is 
+> inspect the (next) nearest neighbor as you're comparing 
+> elements, and then raise PE if Next.Elem < Curr.Elem.  But 
+> once the source has been merged onto the target however, then 
+> no further inspection should be required.
+
+Thinking about this more, I realized that no is-sorted checks are required.
+
+As you process the source list, you compare its front element to the element
+at the current position in the target list.  The rule is that if the source
+element is less than the target element, then the source element is spliced
+immediately before that target element.  Otherwise you move to the next
+position in the target list, and the process then repeats.
+
+If the source list isn't in sort order, then all that happens is that the
+sublist of descending source elements are spliced onto the target before the
+current position.  There is nothing special about the source elements here
+as far as the merge is concerned, since these are just source elements that
+are less than the current target element, and hence get spliced onto the
+target in the normal way.
+
+If the target list isn't in sort order, then the descending elements of the
+target sublist will all be less than the front of the source, and merge will
+just consume them in the normal way.  Again there is nothing special about
+this sublist as far as merge is concerned.
+
+In both cases the output is perfectly predictable.  Hence I conclude that
+the original semantics were correct, and no is-sorted check is necessary.
+Program_Error should only be raised if the algorithm is unable to deliver a
+result, but that is not the case here.  Indeed, the result is well-defined.
+
+****************************************************************
+
+From: Christoph Grein
+Sent: Wednesday, April 6, 2005  11:50 PM
+
+I think Matthew is right here. I also find it very odd (to say the least) to get
+Program_Error _and_ a well-defined result. This is counter-intuitive and contrary
+to any other place in the RM where you cannot rely on the results of a 
+subprogram when an exception is raised.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Thursday, April 7, 2005  12:33 PM
+
+But the RM has to say *something* about the state of the containers.  It
+used to say that their state was *unspecified* after raising P_E, and as
+you know one of the possible outcomes for unspecified is *erroneous*.
+Technically, this means that after you have run into this situation, the
+behavior of the program may become completely unpredictable: other
+containers may be corrupted, random storage leaks can happen, etc.  Heck,
+for all we know the P_E may not even be propagated because the exception
+runtime may be confused.
+
+Of course in practice implementers are not going to sabotage their
+implementation, but it is still a good idea to avoid erroneousness
+whenever possible.  This is not always possible, and there are situations
+where the implementation cost needed to prevent erroneousness would be too
+high.  In the case at hand, though, there is really no difficulty: if the
+implementation finds that one of the containers is out of order, it just
+needs to append Source to Target and raise P_E.  While we don't expect
+that the user will handle/recover from this exception, at least we know
+that the program will proceed deterministically, that no corruption will
+happen, and that the exception will be propagated as expected.
+
+I believe that saying *unspecified* here would be actively harmful for no
+good reason.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Thursday, April 7, 2005  1:05 AM
+
+Just a clarification of that last remark.  The containers are all
+pass-by-reference types, implying that even when an exception is propagated
+out of a subprogram, the container is guaranteed to have a consistent state.
+For some exceptions the RM doesn't say exactly what that state is, only that
+the container continues to be usable qua container.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, April 7, 2005  3:27 PM
+
+Pascal wrote:
+
+...
+> But the RM has to say *something* about the state of the containers.  It
+> used to say that their state was *unspecified* after raising P_E, and as
+> you know one of the possible outcomes for unspecified is *erroneous*.
+...
+> I believe that saying *unspecified* here would be actively harmful for no
+> good reason.
+
+There are other choices, of course. In this case, saying that the *order* of
+the elements is unspecified should be fine. I don't see how anyone could
+interpret an unspecified order to cause random havoc.
+
+That is, if the Source or Target are not sorted, the result is that all of
+the elements are in Target, in an unspecified order.
+
+That said, I am very torn on this issue. When the preconditions aren't met,
+the postcondition isn't met either. So it would be best to inform the user
+of that. Moreover, most of the time, the operation will detect that the
+parameter(s) are unsorted with little additional work. OTOH, we don't want
+to take a lot of extra overhead to do detect this case.
+
+Perhaps the best solution would be to call this a bounded error (it is,
+really); with the above wording (the order is unspecified). Then an
+implementation *can* raise Program_Error (with the conditions already
+noted), or it can leave the elements in some order. We also could add some
+IA suggesting that Program_Error be raised if it is not too expensive; then
+the decision would be up to the implementer.
+
+Remember that a lot of text in the standard (including this clause) abuse
+the meaning of unspecified. In this clause, it is really intended to mean
+"some result, which does not need to be documented, but not abnormal or
+erroneous execution". I was told not to fix that here, because it would get
+very messy, and there are many other places in the Standard with the same
+problem.
+
+****************************************************************
+
+From: Christoph Grein
+Sent: Thursday, April 7, 2005  11:18 PM
+
+I know that containers are by-reference types, but also for those types, you
+don't generally know in which state they were left when an exception was 
+raised, or do you?
+
+So what's the reason for the RM to specify the final state even with exceptions. Or
+does it specify only the result for this one exception Program_Error?
+
+But PE is one of the worst exceptions, meaning your program is corrupted. And still
+you define the exact state of the containers...?
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, April 8, 2005  12:00 AM
+
+Christophe Grein writes:
+
+> I know that containers are by-reference types, but also for those types, you
+> don't generally know in which state they were left when an exception was
+> raised, or do you?
+>
+> So what's the reason for the RM to specify the final state even with exceptions. Or
+> does it specify only the result for this one exception Program_Error?
+
+The exact details of a container (or any other by-reference type) is not
+necessarily known, but the object is not abnormal. If using it causes things
+to blow up, it's solely because of the implementation of the object, and
+that is preventable.
+
+One of the language design principles states (it's A.18(4.u) in the draft 11
+AARM, but that hasn't been distributed yet; it may be different or absent in
+draft 10, and it's somewhere toward the start of the AI):
+
+It is expected that exceptions propagated from these operations do not
+damage containers.
+
+It goes on to explain why that isn't said normatively in every case (mainly
+that it would be very complex to do so). But the intent is that an
+implementation that destroys containers is wrong. In this case, we're
+trusting implementers to follow the notes and not do something that it
+harmful to users. Its the same as saying that "unspecified" means "some
+result but not erroneous".
+
+There are a number of cases where we do specify more about the contents
+after an exception. That is usually done in cases where the exception should
+be raised before any modifications are done, but it's also done to insure
+that implementations don't drop elements on the floor.
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Friday, April 8, 2005  2:59 AM
+
+> But PE is one of the worst exceptions, meaning your program is 
+> corrupted. And still > you define the exact state of the containers...?
+ 
+I agree that P_E should be reserved for severe problems (i.e. things 
+that we would like to detect at compile-time, but it is not possible - 
+like accessibility violations).
+
+Why don't we have a Container_Error exception?
+
+****************************************************************
+
+From: Christoph Grein
+Sent: Friday, April 8, 2005  5:09 AM
+
+Exactly!
+
+****************************************************************
+
+From: Simon J. Wright
+Sent: Friday, April 8, 2005  5:56 AM
+
+There might be an argument for Constraint_Error here ..
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005 12:19 AM
+
+> I know that containers are by-reference types, but also for 
+> those types, you don't generally know in which state they 
+> were left when an exception was raised, or
+> do you?
+
+Sometimes the exception is raised because the parameters are bad, so in that
+case there is no state change.  You're just checking preconditions to
+prevent damage.  The canonical example is raising PE if a cursor doesn't
+designate an element from the same container.  (This check is in fact why we
+implemented cursors as a fat pointer.)
+
+In other cases, and exception is raised to indicate that the postcondition
+could not be satisfied.  This is usually (always?) Storage_Error.
+
+Most of the time there is no state change, and I think the RM states this
+where applicable.
+
+In a few other cases, Storage_Error is propagates but how much state change
+there is is left unspecified.  For example, if you insert N number of items
+into a list, then Storage_Error can get raised if you're unable to allocate
+all N items.  But the RM doesn't say by how much the cardinality of the list
+changed.
+
+(Note, I must quality that last paragraph by stating that the current RM
+says that there is no state change.  So technically what I said in the last
+paragraph is incorrect.  I did post a note to ada-comment for the ARM to
+confirm what the RM says, because I believe the RM is wrong here.)
+
+In other cases, the implementation simply propagates exceptions raised by
+subprograms supplied by the user.  For example, if a generic actual Hash
+function raises an exception, then it is propagated.  Sometimes this means
+that state has changed, and there's no way for the RM to specify the exact
+state.  However, the RM does guarantee that the container isn't broken;
+implementers do have the burden of gracefully tolerating exceptions raised
+by user subprograms.
+
+Generic_Merge is a unique case, since you can't detect the "error" (the
+lists aren't in sort order) until you've modified the state.  I put the word
+"error" in scare quotes because I don't like the semantics as they exist
+today.  Generic_Merge works, and does exactly the right thing, even if the
+lists aren't sorted.  There is no reason for the checks, or for the
+Program_Error.
+
+
+> So what's the reason for the RM to specify the final state even with 
+> exceptions. 
+
+Because usually there isn't a state change.
+
+If the precondition failed, then there's no state change.
+
+If the allocation failed (meaning you're unable to satisfy a postcondition),
+then that often happens early, before the state is modified.  In my
+reference implementation, I take great pains to attempt the allocation
+before modifying any state, and just allow the Storage_Error to propagate.
+
+But sometimes state must get modified before there's an error.  For example,
+if you Clear a list, and deallocation of one of the elements fails (say,
+controlled finalization propagates PE), then the RM doesn't say that the
+state of the container is.  The only thing that is required is that the
+container not be broken.  If you notice in my reference implementation, I
+unlink the node and then immediately restore invariants, and only after that
+do I attempt the deallocation.  Even if the deallocation of the unlinked
+node fails, I still leave the list in a consistent state.
+
+
+> Or does it specify only the result for this one exception Program_Error?
+
+So far Generic_Merge is a unique case.  (I'm still reviewing the AI, and
+updating the reference implementation.)
+
+As I stated above and in earlier messages, I think the semantics of
+Generic_Merge are terribly wrong, among other reasons because it mandates an
+O(n) check.
+
+
+> But PE is one of the worst exceptions, meaning your program is 
+> corrupted. And still
+> you define the exact state of the containers...?
+
+Sometimes PE gets raised because a precondition fails.
+
+I do think it's odd to require that Generic_Merge splice the source onto the
+end of the target (why on the end???) and then raise PE.  But my particular
+issue with the semantics of Generic_Merge is that we have the check at all,
+since with the original semantics the algorithms behaves over all inputs,
+sorted or otherwise.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 5, 2005  9:30 PM
+
+AA-A.TXT says
+
+86/2  procedure Insert (Container : in out List;
+                        Before    : in     Cursor;
+                        New_Item  : in     Element_Type;
+                        Count     : in     Count_Type := 1);
+
+    87/2  {AI95-00302-03} ... Any exception raised
+          during allocation of internal storage is propagated, and Container
+          is not modified.
+
+MJH:
+
+Is that last part about "Container is not modified" correct?  I think that
+text is vestigial, from the time before which there was no additional Count
+parameter.
+
+I think it's the case that if there's a Storage_Error, then an
+implementation is allowed to have modified the container, by inserting some
+new items (some number less than Count).
+
+But maybe I'm wrong, and these are the intended semantics.  I just wanted to
+clarify.
+
+ENDMJH.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Sunday, April 10, 2005  10:11 AM
+
+About the four-parameter Splice operation for lists, AA-A.TXT says:
+
+113/2 procedure Splice (Target   : in out List;
+                        Before   : in     Cursor;
+                        Source   : in out List;
+                        Position : in     Cursor);
+
+MJH:
+
+I believe this declaration is incorrect.  The Position parameter needs to be
+mode inout, not mode in.
+
+It is more or less necessary to implement a cursor with a pointer to the
+associated container as part of its representation.  The issue is that
+Position is a curssor that designates a node that migrates from list Source
+to list Target.  Therefore the Position cursor value must change, to update
+the internal container pointer, so that it changes from Source to Target.
+
+The updated declaration should be:
+
+   procedure Splice (Target   : in out List;
+                     Before   : in     Cursor;
+                     Source   : in out List;
+                     Position : in out Cursor);
+
+ENDMJH.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Sunday, April 10, 2005 11:18 PM
+
+AA-A.TXT says:
+
+111/2 procedure Splice (Target   : in out List;
+                        Before   : in     Cursor;
+                        Position : in     Cursor);
+
+    112/2 {AI95-00302-03} ...If Position equals No_Element ... the operation
+           has no effect.
+
+
+113/2 procedure Splice (Target   : in out List;
+                        Before   : in     Cursor;
+                        Source   : in out List;
+                        Position : in     Cursor);
+
+    114/2 {AI95-00302-03} If Position is No_Element then Constraint_Error is
+          propagated...
+
+MJH:
+
+In the 3-parameter version, if Position equals No_Element, then Splice does
+nothing.
+
+In the 4-parameter version, if Position equals No_Element, then Splice
+propagates Constraint_Error.
+
+Was this difference deliberate?  If so, what was the retionale?
+
+Or is this a bug in the RM?  If so, then which Splice is correct?
+
+ENDMJH.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
 ****************************************************************
 
 From: Matthew Heaney
-Sent: Friday, September 2, 2004  9:31 AM
+Sent: Friday, April 2, 2005  9:31 AM
 
 ****************************************************************
 
 From: Matthew Heaney
-Sent: Friday, September 2, 2004  9:31 AM
+Sent: Friday, April 2, 2005  9:31 AM
 
 ****************************************************************
 
 From: Matthew Heaney
-Sent: Friday, September 2, 2004  9:31 AM
+Sent: Friday, April 2, 2005  9:31 AM
 
 ****************************************************************
 
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
 

Questions? Ask the ACAA Technical Agent