CVS difference for ai05s/ai05-0032-1.txt

Differences between 1.1 and version 1.2
Log of other versions for file ai05s/ai05-0032-1.txt

--- ai05s/ai05-0032-1.txt	2006/12/15 06:29:18	1.1
+++ ai05s/ai05-0032-1.txt	2007/05/19 05:10:44	1.2
@@ -1,4 +1,4 @@
-!standard  6.5(5.2/2)                                         06-12-15    AI05-0032-1/00
+!standard  6.5(5.2/2)                                         07-05-18    AI05-0032-1/01
 !class Amendment 06-11-19
 !status work item 06-11-19
 !status received 06-11-19
@@ -14,17 +14,133 @@
 
 !proposal
 
-[Allow specific types to match class-wide types in extended return statements.]
+Imagine a device driver that registers a constructor function when it is loaded.
+The constructor function returns Device'Class. Device is a limited type.
 
+Consider how you would use an extended return to write the SCSI device
+constructor: 
+
+    return Obj : <specific type> do -- Not legal
+    
+This is not legal because we require the type here to be the same as that of the
+function [defined in 6.5(5.2/2)]. Instead, you have to write: 
+
+    return Obj : Device'Class := Func do 
+    
+where Func is a dispatching call. 
+
+It seems that the first case really should be legal.  An alternative view
+suggests that the example is inappropriate; a constructor should be a
+dispatching function, not something returning a classwide type.   You could
+write a factory this way, but the actual constructs should probably still be
+dispatching routines. However, arguments from usage patterns are difficult to
+decide. Note that this is somewhat similar to the unconstrained case, where we
+allow giving constraints.  For example:
+
+    function F return String is
+    begin
+         return Obj : String(1..10) do ...
+
 !wording
 
-(** TBD **)
+Modify RM 6.5(5.2/2) as follows:
 
-!discussion
+    If the result subtype of the function is defined by a subtype_mark, the
+    return_subtype_indication shall be a subtype_indication. The type of the
+    subtype_indication shall be {covered by} the result type of the function. If
+    the result subtype of the function is constrained, then the subtype defined
+    by the subtype_indication shall also be constrained and shall statically
+    match this result subtype. If the result subtype of the function is
+    unconstrained, then the subtype defined by the subtype_indication shall be a
+    definite subtype, or there shall be an expression.
+    
+Add to the end of RM 6.5(5.8/2):
+
+    ... {If the result type is class-wide, a view conversion of the return
+    object to the function result subtype is evaluated Redundant:[, which might
+    raise Constraint_Error].}
+  
+Modify RM 6.5(8/2) as follows:
+
+    If the result type of a function is a specific tagged type, the tag of the
+    return object is that of the result type. If the result type is class-wide,
+    the tag of the return object is that of {the type of the subtype_indication
+    if it is specific, or otherwise that of} the value of the expression. A
+    check is made that the accessibility level of the type identified by the tag
+    of the result is not deeper than that of the master that elaborated the
+    function body. If this check fails, Program_Error is raised.
+    
+Modify RM 6.5(23/2) as follows:
+
+    In the case of a function, the function_call denotes a constant view of the
+    return object.  {If the result type is class-wide, this view is that created
+    by the view conversion of the return object to the function result subtype
+    (see above).}
 
-** TBD **
+!discussion
 
-!example
+The example in the "problem" section above illustrates how the existing rule can
+be annoying.  Arguing from consistency with the existing ability to specify a
+more constrained subtype in the return_subtype_indication, it seems reasonable
+to allow an object of any type that would satisfy the "expected type" for the
+expression in a simple_return_statement.  The expected type for that expression
+is the function result type.  That means that if the function result type is
+class-wide, then the return expression in a simple_return_statement could be of
+any type covered by the class-wide type.  It seems reasonable therefore to allow
+the declaration of an object of any such type as the return object in an
+extended_return_statement.
+
+Note that the main wording changes are quite simple, namely adding "covered by"
+to paragraph 5.2/2, and specifying that the tag comes from the subtype_
+indication if it is specifc. 
+
+The changes in 5.8/2 and 23/2 are actually patching a hole that already existed,
+since one could have a result subtype of "S1'Class" but specify a nominal
+subtype for the return object of "S2'Class" where S1 and S2 are both subtypes of
+the same type, and nowhere were we checking that the return object satisfied the
+constraints of S1.
+
+Actually, there is a bigger problem here, because it appears that in 4.6 (Type
+Conversions) we don't ever do the discriminant check you would expect if you
+convert S2'Class to S1'Class.  The relevant sentence would be the first sentence
+of RM 4.6(51/2):
+  
+    After conversion of the value to the target type, if the target subtype is
+    constrained, a check is performed that the value satisfies this
+    constraint...
+
+Unfortunately, all subtypes of a class-wide type are considered unconstrained,
+because they have unknown discriminants.  Furthermore, I'm not sure we ever
+specify what it means to "satisfy" the constraint associated with S1'Class,
+though it probably wouldn't be too hard if we first do a view conversion to 
+the type of S1, and then check the discriminants of that view against the
+constraints of S1.
+
+So the changes suggested above for 6.5(5.8,23) are sort of irrelevant if we
+don't also add something to 4.6(51).  That should probably be a separate AI.
+
+    -- Every device kind needs a constructor that creates a device control
+    -- block for that kind of device.  This constructor is registered
+    -- in a table indexed by the device kind ID.
+    type Device_Constructor is access function (P : Param) return Device'Class;
+    
+    procedure Register_Device_Constructor(Kind : Device_Kind_ID;
+      Constructor : Device_Constructor);
+      
+    ....
+      
+    -- Here we define such a constructor, and then register it
+    -- Note that it is natural to make the return object of the
+    -- specific device type, rather than the class-wide type
+    -- used for the function result subtype.
+    function Make_My_Device(P : Param) return Device'Class is
+    begin
+        return Result : My_Device do
+            Init_My_Device(Result);
+        end return;
+    end Make_Device;
+  begin
+    Register_Device_Constructor(My_Device_Kind, Make_My_Device'Access);
 
 !ACATS test
 
@@ -32,5 +148,51 @@
 
 !appendix
 
+From: Tucker Taft
+Sent: Friday, May 18, 2007  8:37 AM
+
+Here is the AI [This is version /01 of the AI - ED]
+on allowing the type of the return object
+in an extended_return_statement to be a specific type when
+the result type is class-wide.  While writing this, I bumped
+into what seems to be a longstanding hole in 4.6 (Type
+Conversions).  Given two subtypes of T'Class, S1'Class
+and S2'Class, we don't ever seem to check that when converting
+from S2'Class to S1'Class, that the operand satisfies
+the constraints of S1.  See the AI discussion section for
+more on this.  A related hole seems to exist in 6.5
+(Return Statements), where if the result subtype is
+S1'Class, we allow the return object to be declared of
+subtype S2'Class, and again never check against S1.
+I tried to fix this latter hole, but ended up just
+presuming that 4.6 did the right thing, which it doesn't.
+So another AI is probably needed to address the 4.6 hole.
+
+Ignoring this particular existing hole, the wording changes
+were quite small.
+
 ****************************************************************
 
+From: Randy Brukardt
+Sent: Friday, May 18, 2007  11:17 PM
+
+I don't understand your hole. I don't think there is any hole in 6.5,
+at least before your proposal. 6.5(5.2/2) requires static matching
+of the return object subtype if the result subtype is constrained;
+so if the result subtype S1'Class has a constraint, an object subtype
+of S2'Class is illegal unless it has the same constraints. If the
+result subtype doesn't have a constraint, there is nothing to check.
+
+Humm, 4.6(51/2) says that after the conversion, there is a check that
+the value satisfies any constraint of the target subtype if it is
+constrained. What more do you need?
+
+(If, for some bizarre reason, S1'Class is not considered constrained,
+then it has no real constraints, because pretty much all of the rules
+of the language are written "if constrained, then blah blah". It would
+effectively act like was unconstrained. While I'd prefer this
+interpretation, I don't think it was what was intended - I remember
+*losing* that argument during Ada 95. And having constraints on
+unconstrained subtypes seems like the first step on the road to madness...)
+
+****************************************************************

Questions? Ask the ACAA Technical Agent