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

Differences between 1.3 and version 1.4
Log of other versions for file ai12s/ai12-0223-1.txt

--- ai12s/ai12-0223-1.txt	2018/05/10 06:07:32	1.3
+++ ai12s/ai12-0223-1.txt	2018/06/12 05:28:47	1.4
@@ -247,3 +247,184 @@
 
 ****************************************************************
 
+From: Jean-Pierre Rosen
+Sent: Tuesday, May 22, 2018  9:16 AM
+
+Taking up this AI from where it was left...
+
+The killing problem noted by Randy is (from the AI):
+-------------------------
+For the example given in the problem, that would give:
+
+    type Map_Rec, Map_Rec_Cursor is new
+       My_Map_Pkg.Map with private, My_Map_Pkg.Cursor;
+
+This is known not to work in various cases.
+
+The most important is that it doesn't make sense for dispatching. If one of
+the types is tagged (both cannot be tagged, as that would imply a type 
+primitive for two tagged types, which is not allowed in Ada), then one would
+get inherited dispatching routines.
+
+For instance, with the above declaration, we'd inherit delete, which is 
+defined as:
+
+   procedure Delete (Container : in out Map;
+                     Position  : in out Cursor);
+
+which would be inherited as:
+
+   procedure Delete (Container : in out Map_Rec;
+                     Position  : in out Map_Rec_Cursor);
+
+However, a dispatching call on My_Map_Pkg.Map'Class would call:
+
+   procedure Delete (Container : in out Map_Rec;
+                     Position  : in out My_Map_Pkg.Cursor);
+
+which doesn't exist.
+-----------------------------------------------
+Is it really a problem? Important points to keep in mind:
+1) Coderivation does not imply multi-dispatch, since at most one type is 
+tagged.
+2) Derived non-tagged types are equivalent (assuming no change in 
+representation), and calls to primitive operations are always statically 
+bound.
+
+So it seems harmles for the co-derived subprogram to use the same slot in 
+the dispatch table as the original one, i.e. a dispatching call on some 
+Container will call the Delete on Map_Rec_Cursor if the dispatching call
+is on Map_Rec, and the Delete on Cursor if the dispatching call is on Map.
+
+Where could such a dispatching call happen? Presumably within a procedure 
+like:
+
+Do_Something (Container : in out Map'Class;
+              Position  : in out Cursor);
+
+Now, the user has declared:
+My_Cont : Map_Rec;
+My_Curs : Map_Rec_Cursor;
+
+He can call:
+Do_Something (My_Cont, Cursor (My_Curs));
+
+(Annoying conversion, see later)
+
+Inside Do_Something, there is a call:
+Delete (Container, Position);  -- Dispatching
+
+In this case, the dispatching table will point to the co-derived subprogram 
+=> it works as expected.
+
+1) Extra point 1:
+This assumes that there is no change of representation for the derived type - 
+i.e. changes of representation would not be allowed for types that are part of
+a coderivation. Or alternatively, co-derivation would not be allowed if a non 
+tagged type has a change of representation. This seems a small price to pay 
+for the feature.
+
+2) Extra point 2:
+The extra conversion in the call:
+ Do_Something (My_Cont, Cursor (My_Curs)); is annoying. It could be avoided by 
+allowing T'Class on non-tagged types ONLY IN FORMAL PARAMETERS  (trying to 
+quickly jump into my asbestos suit), with the obvious meaning: compatible with
+any type derived from it, perhaps also under the condition that there is no 
+change of representation.
+
+Thoughts?
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thrusday, June 7, 2018  7:31 PM
+
+...
+> Where could such a dispatching call happen? Presumably within a 
+> procedure like:
+> 
+> Do_Something (Container : in out Map'Class;
+>               Position  : in out Cursor);
+> 
+> Now, the user has declared:
+> My_Cont : Map_Rec;
+> My_Curs : Map_Rec_Cursor;
+> 
+> He can call:
+> Do_Something (My_Cont, Cursor (My_Curs));
+
+True, but he's totally lost static type checking. The routine can no longer 
+know whether it is getting the right type.
+
+Nothing prevents calling Do_Something with mixed types, such as:
+
+My_Other_Cont : Map_Rec;
+My_Other_Curs : Cursor;
+
+Do_Something (My_Other_Cont, Cursor (My_Other_Curs));
+
+...and now you'll dispatch to the primitive routine Delete with the wrong kind
+of cursor.
+
+That is, it will work in the "correct" case, but it also will allow many 
+incorrect calls.
+
+If you're going to lose most of the type checking, you might as well not 
+bother with the co-derivation.
+
+...
+> 1) Extra point 1:
+> This assumes that there is no change of representation for the derived 
+> type - i.e. changes of representation would not be allowed for types 
+> that are part of a coderivation. Or alternatively, co-derivation would 
+> not be allowed if a non tagged type has a change of representation. 
+> This seems a small price to pay for the feature.
+
+The tagged type is not the problem, and it should be allowed to have a change
+of representation. Untagged types with primitive routines never allow change
+of representation (except via a language bug) - see 13.1(10). So this doesn't
+seem to be a problem unless we decide to remove the nasty (and incompletely
+enforced) 13.1(10).
+
+> 2) Extra point 2:
+> The extra conversion in the call:
+>  Do_Something (My_Cont, Cursor (My_Curs)); is annoying. It could be 
+> avoided by allowing T'Class on non-tagged types ONLY IN FORMAL 
+> PARAMETERS  (trying to quickly jump into my asbestos suit), with the 
+> obvious meaning: compatible with any type derived from it, perhaps 
+> also under the condition that there is no change of representation.
+
+That would work, but you'd still have the typing problem noted above.
+
+The way to fix the typing problem would be to require that both types be 
+tagged (not currently allowed). We'd only allow co-derivation for such types,
+so their tags would always be related. That would avoid the problems of 
+multiple dispatch. (I don't think the tags could be the same, because 
+predefined single type stuff like streaming and assignment has to be different
+for each type. But the routines with multiple controlling parameters would 
+have to be present in both tags, and designate the same subprogram.)
+
+We already have a check for any subprogram that has multiple controlling 
+parameters that the tags match. We could replace that by a rule that the tags
+have to have the same relationship (come from the same co-derivation). In that
+case, dispatching would always go to the routine with the correct parameter.
+
+A dispatching routine would thus have to have dynamically tagged values (or
+statically tagged) for both parameters. And 'Class is automatically available.
+So Do_Something could be declared:
+
+Do_Something (Container : in out Map'Class;
+              Position  : in out Cursor'Class);
+
+I think this would solve the typing problem, but I don't know if it works for
+the generic derived type issues that Steve (who else?) raised privately with 
+me. And I don't know if it would interfere with any other language mechanisms.
+Someone more motivated than me needs to figure that out.
+
+P.S. It also would be an issue with the existing containers. Not sure if 
+making Cursors tagged would be compatible enough; it would make regular 
+derivations of them (and containerss) illegal. I think the result would be 
+much better (if the code was rewritten to use coderivation), but the code 
+breakage might be too much to stomach.
+
+****************************************************************

Questions? Ask the ACAA Technical Agent