CVS difference for 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