CVS difference for ai05s/ai05-0188-1.txt
--- ai05s/ai05-0188-1.txt 2011/02/12 04:31:12 1.15
+++ ai05s/ai05-0188-1.txt 2011/02/16 04:25:41 1.16
@@ -1686,3 +1686,524 @@
and I think the wording I proposed yesterday would allow this.
****************************************************************
+
+From: Steve Baird
+Sent: Wednesday, February 2, 2011 3:10 PM
+
+> If you have a case-expression in a generic package spec which cases
+> on, say, a ormal in-out object of type Integer, it must cover all the Integer values.
+>
+> If you then instantiate the generic with an object whose subtype is
+> Natural, I don't think we want to see a legality violation upon
+> rechecking the expanded spec for the instance.
+
+Randy reminded Bob and me that this issue was never resolved.
+
+In subsequent discussions, it was noticed that the same problem already exists
+for variant parts, as in
+
+ procedure Vp_In_Inst is
+ generic
+ type T is new Integer;
+ package G is
+ type Rec (Discrim : T) is record
+ case Discrim is
+ when -10 .. -1 =>
+ Foo : Float;
+ when others =>
+ null;
+ end case;
+ end record;
+ end G;
+
+ package I is new G (Natural); -- legal?
+ begin
+ null;
+ end Vp_In_Inst;
+
+It seems that we ought to treat the two situations (variant parts and case
+expresssions) consistently.
+
+One alternative is to do nothing: both the above example and similar examples
+involving case expressions would be illegal.
+
+This seems unfriendly (especially for case expressions), but it is well defined.
+
+Alternatively, the following wording changes would allow these constructs to be
+accepted:
+
+Add at the end of the 3.8.1 Legality Rules section:
+
+ To be honest:
+ The above rule that "each non-others discrete_choice shall cover only
+ values in that subtype" does not apply to a discrete_choice which
+ occurs within an instance of a generic unit.
+
+Similarly, immediately after the existing wording for case expressions,
+
+ All Legality Rules that apply to the discrete_choices of a
+ case_statement (see 5.4), apply to the discrete_choices of a
+ case_expression.
+
+add
+
+ To be honest:
+ The rule for case statements (see 5.4) that in certain situations,
+ "... each non-others discrete_choice shall cover only values
+ in that subtype, ..." does not apply to a discrete_choice which
+ occurs within an instance of a generic unit.
+
+What do folk think?
+
+If someone dislikes using "To Be Honest" clauses in this way, we could discuss
+that as a separate question.
+
+****************************************************************
+
+From: Gary Dismukes
+Sent: Wednesday, February 2, 2011 3:34 PM
+
+...
+> This seems unfriendly (especially for case expressions), but it is
+> well defined.
+
+I agree that it would be unfriendly. I don't think that the error is likely to
+be helpful in this case. Why limit functionality in this way for no strong
+reason? If such constructs are allowed in bodies, they should also be legal in
+specs, I think.
+
+> add
+>
+> To be honest:
+> The rule for case statements (see 5.4) that in certain situations,
+> "... each non-others discrete_choice shall cover only values
+> in that subtype, ..." does not apply to a discrete_choice which
+> occurs within an instance of a generic unit.
+>
+> What do folk think?
+
+I could live with that, but...
+
+> If someone dislikes using "To Be Honest" clauses in this way, we could
+> discuss that as a separate question.
+
+... I'd prefer to have normative text that addresses this.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, February 2, 2011 3:42 PM
+
+These don't seem like "to-be-honest"-ish statements.
+
+I don't see this as a big enough
+issue to justify any changes. It is also one of those things that could be done
+later if people start finding this is a significant problem, since it is only
+making illegal programs legal.
+
+The fact that no one has ever encountered this with variant parts in 30 years
+makes me a little less worried... ;-)
+
+****************************************************************
+
+From: Steve Baird
+Sent: Wednesday, February 2, 2011 3:54 PM
+
+Gary wrote:
+> ... I'd prefer to have normative text that addresses this.
+
+Tucker wrote:
+> These don't seem like "to-be-honest"-ish statements.
+
+Fine with me.
+
+So if we decide to do anything at all about this problem, we'll use "real"
+legality rules.
+
+Tuck advocates doing nothing.
+
+A pragmatic case could be made for treating the two constructs inconsistently.
+As Tuck notes, there have never been any complaints about the variant_part
+situation. On the other hand, this seems like it might be more of a problem for
+case expressions.
+
+So alternatives include
+ 1) Do nothing
+ 2) Add permissive legality wording only for case expressions.
+ 2) Add permissive legality wording for both case expressions and
+ variant parts.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, February 2, 2011 5:12 PM
+
+Are we really convinced it is a good idea to make this change? If a case
+expression in the generic spec specifies what should be done with particular
+values, and the actual type doesn't have those values, doesn't that sound like
+something is awry? Is this that different from initializing a named constant of
+the formal type to a particular literal value, when that literal value turns out
+to be outside the range of the formal subtype?
+
+****************************************************************
+
+From: Steve Baird
+Sent: Wednesday, February 2, 2011 5:31 PM
+
+> Are we really convinced it is a good idea to make this change?
+
+I don't think we've reached a consensus on this point. I think this problem is
+worth addressing, at least for case expressions (the only real argument for
+messing with variant parts is consistency), but I agree that it is a judgment
+call and that taking no action is a reasonable alternative.
+
+You'd prefer to take no action.
+
+Gary said "I agree that it would be unfriendly" to reject the case expressions
+we've been discussing.
+
+I'd like to get other opinions.
+
+> If a case expression in the
+> generic spec specifies what should be done with particular values, and
+> the actual type doesn't have those values, doesn't that sound like
+> something is awry?
+
+This seems no worse than calling a function which takes an Integer paremeter and
+passing it the value of a variable whose subtype is Natural. The function may
+provide all sorts of support for the case where it is passed a negative value
+and, for this particular call, that code will never be exercised.
+
+> Is this that
+> different from initializing a named constant of the formal type to a
+> particular literal value, when that literal value turns out to be
+> outside the range of the formal subtype?
+
+Yes, it is different. Now you are talking about a situation where the
+instantiator requires functionality which the generic doesn't provide, as
+opposed to failing to make use of the full functionality which the generic does
+provide.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Wednesday, February 2, 2011 6:11 PM
+
+> Are we really convinced it is a good idea to make this change?
+
+In the abstract, it seems like a good idea, to me.
+The only negative, to me, is that maybe it's not worth the trouble. Most
+variant records, and probably most case expressions, are on regular non-formal
+enumeration types.
+
+>... If a case expression in the
+> generic spec specifies what should be done with particular values,
+>and the actual type doesn't have those values, doesn't that sound like
+>something is awry? Is this that different from initializing a named
+>constant of the formal type to a particular literal value, when that
+>literal value turns out to be outside the range of the formal subtype?
+
+I don't buy that analogy, for the reason Steve gave.
+
+A better analogy is a case statement, which must appear in the generic body, and
+can specify nonexistent values in an instance. (In fact, case expressions in
+the body will work that way.)
+
+The reason to forbid "when -1" when the subtype is Natural, is that that's
+almost certainly a mistake. But in the generic case, you don't KNOW it's
+Natural -- it just happens to be in one instance, but other instances might need
+that -1 case.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, February 2, 2011 8:22 PM
+
+> In subsequent discussions, it was noticed that the same problem
+> already exists for variant parts, as in
+...
+> What do folk think?
+
+If you had waited for me to answer your original question (which has been
+delayed by the need to dig out from 19" of snow that we've gotten since Monday
+afternoon, along with the steady 35 MPH wind), you would have already found out
+that I think that you've lost your mind. (I should have simply buried your
+original question, but I didn't think about it as I was in a hurry to leave
+before my car was too buried to move.)
+
+Let me explain the ways:
+
+(1) Using a To Be Honest note to change how legality rules work is completely
+ insane. TBHs are intended for cases where we say *almost* what we mean, but
+ leave out some something for clarity. Not for cases where we are changing
+ the rules from check to not check!
+
+(2) There is almost no similarity between the variant case and the case
+ expression/statement case. Tucker noted that no one has run into this in 30
+ years, but he didn't explain why.
+
+A variant like this in a generic body is just short of a pathology. The reason
+is that you cannot write any aggregates for such a type. The discriminant of an
+aggregate that controls variant components has to be static. But no expression
+of a generic formal type can ever be static - a generic formal subtype is never
+a static subtype, so there can be no static expressions of such a subtype. Thus
+there cannot be any aggregates.
+
+Without aggregates, constructing values of a variant record is a chore -- you
+have to declare an object of a constrained subtype and then fill in the
+components individually. I can imagine doing that if you need to export such a
+type, but not otherwise. So I don't think that there can be many such types in
+bodies.
+
+OTOH, it does make sense to export such a type from a generic specification (the
+instantiator can create objects freely). In that case, having variants that you
+can't use is not likely to be a good thing.
+
+In contrast, a case expression, even when used in a generic specification, is
+evaluated there; the instantiator can only access the value of that evaluation
+(it never uses the expression in any other way). So it doesn't matter as much
+what rules are used.
+
+(3) The primary benefit of case expressions is completeness checking. Indeed,
+ without that I would have voted against them as an unnecessary frill. But
+ you have to include an "others" clause for any case statement or expression
+ of a generic formal type. The effect is to make them much less useful;
+ meaning that if you have to convert them to if-expressions, this is not
+ going to cause any less safety in your program.
+
+(4) Darn, after reading 4.9 again, it appears that numeric literals can be
+ static even if they have a formal subtype. So (2) isn't quite right above.
+ But note that the operators of a formal subtype are NOT static functions
+ (4.9(19)), so "-1" is NOT static in this case. (Recall that we don't use the
+ universal operators if a subtype is expected for an expression, rather we
+ use the operators of that subtype.)
+
+So the variant in Steve's example is illegal in the generic:
+
+ generic
+ type T is new Integer;
+ package G is
+ type Rec (Discrim : T) is record
+ case Discrim is
+ when -10 .. -1 =>
+ Foo : Float;
+ when others =>
+ null;
+ end case;
+ end record;
+ end G;
+
+since neither "-10" nor "-1" are static, and that violates 3.8.1(8). The same is
+true for case statements and case expressions (5.4(5)). (It might have been
+legal in the instance, but you'll never get there.)
+
+Similarly, you can use named numbers in such cases and variants, but not
+constants (they're not static, either, in this case, nor is a type conversion
+from a static constant of some other type).
+
+So you are very limited in what you can do with such things; essentially you can
+only use positive literals.
+
+You could still construct problems, but I find it hard to believe that these are
+very common.
+
+Also note that the rules about static expressions would apply in the instance
+(4.9(33-37)). Even if you waived the case/variant rules, you'd still have the
+possibility of illegal instances because violating one of these rules. That
+would be implementation-dependent in the case of the base range rule, which
+doesn't seem to be adding anything positive to the language!
+
+To summarize:
+
+It seems to me that there would need to be a lot of rewording to support this
+case, it would be clearly harmful for exported types, there is no bad effect
+from using an if expression instead of a case expression (no completeness check
+is possible anyway), most such case expressions are illegal anyway.
+
+So I think leaving the rules as they are is best.
+
+Note that I wouldn't object strongly to changing this for case
+expressions/statements only, but I don't think it is worth the effort.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Thursday, February 3, 2011 12:36 PM
+
+> ... I think that you've lost your mind.
+
+As I mentioned earlier, there seems to be general agreement that
+ 1) We don't want to make any changes relating
+ to variant parts.
+ 2) If we do make a change relating to case expressions,
+ we want to do it via a first-class legality rule,
+ not via a TBH note.
+
+Given that I agree with the above and feel that the only remaining question is
+whether we should do anything at all for case expressions, do you think that I
+need to continue the search for my missing mind?
+
+> The primary benefit of case expressions is completeness checking.
+
+Agreed. I think that there are others-less case expressions that can run afoul
+of this problem:
+
+ generic
+ X : in out Integer;
+ package G is
+ Inc_X_Towards_Zero : constant Integer :=
+ (case X is
+ when Integer'First .. -1 => X + 1,
+ when 0 => 0,
+ when 1 .. Integer'Last => X - 1
+ end case);
+ end G;
+
+ Z : Natural := ...;
+
+ package I is new G (Z); -- legal?
+
+Hopefully I got the syntax right, but you get the idea in any case.
+
+> Also note that the rules about static expressions would apply in the
+> instance (4.9(33-37)). Even if you waived the case/variant rules,
+> you'd still have the possibility of illegal instances because
+> violating one of these rules.
+
+You bring up an interesting point.
+I'm not proposing this, but this could be used as an argument for modifying the
+definition of "statically unevaluated" to handle this case. Right now we have
+
+ a dependent_expression of a case_expression whose expression is
+ static and not covered by the corresponding discrete_choice_list.
+
+This could be somehow generalized so that the "X + 1" expression in the above
+example (in the instance, not in the generic) is statically unevaluated.
+
+I say wait until someone complains about this one.
+
+****************************************************************
+
+From: Jean-Pieere Rosen
+Sent: Thursday, February 3, 2011 3:20 AM
+
+> Gary said "I agree that it would be unfriendly" to reject the case
+> expressions we've been discussing.
+>
+> I'd like to get other opinions.
+>
+I side with Gary on this one.
+
+Nothing bad can happen from the instantiation, why reject it?
+Note that it is different from the case of a variable when the actual type is
+Natural, and the variable is initialized to a negative value: Constraint_Error
+has to be raised. And still, the instantiation is allowed.
+
+Does anybody really want to reject a case that works perfectly, while not
+rejecting a case which is statically known to raise constraint_Error?
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, February 3, 2011 3:36 PM
+
+> > ... I think that you've lost your mind.
+>
+> As I mentioned earlier, there seems to be general agreement that
+> 1) We don't want to make any changes relating
+> to variant parts.
+> 2) If we do make a change relating to case expressions,
+> we want to do it via a first-class legality rule,
+> not via a TBH note.
+>
+> Given that I agree with the above and feel that the only remaining
+> question is whether we should do anything at all for case expressions,
+> do you think that I need to continue the search for my missing mind?
+
+Perhaps it is I who has lost his mind. :-) See below.
+
+> > The primary benefit of case expressions is completeness checking.
+>
+> Agreed. I think that there are others-less case expressions that can
+> run afoul of this problem:
+>
+> generic
+> X : in out Integer;
+> package G is
+> Inc_X_Towards_Zero : constant Integer :=
+> (case X is
+> when Integer'First .. -1 => X + 1,
+> when 0 => 0,
+> when 1 .. Integer'Last => X - 1
+> end case);
+> end G;
+>
+> Z : Natural := ...;
+>
+> package I is new G (Z); -- legal?
+>
+> Hopefully I got the syntax right, but you get the idea in any case.
+
+Interesting. This example exists because the case choices complete the base
+range of the type of the selector expression (the subtype of a formal in out is
+never considered static).
+
+I don't much care about formal in outs (they're rarely used). I do care about
+the similar cases in generic formal subprograms.
+
+I was concerned that there was a new hole here, but I think it is already
+plugged.
+
+ subtype Short_Int is Integer range 0 .. 100;
+
+ generic
+ with function Foobar (A : Short_Int) return Short_Int;
+ package Gen is
+ Something : constant Boolean :=
+ (case Foobar (1) is
+ when 1 .. 100 => True,
+ when 0 => False); -- (1)
+ end Gen;
+
+This case expression is illegal, as not all of the values of the base range of
+the type of the selector expression are covered. That's because the result
+subtype of a formal function is never considered static. That's good, as the
+actual could have been
+
+ function "-" (Right : in Integer) return Integer;
+
+and it would return "-1" in this case.
+
+I was concerned that there was a way to do this with other sorts of formals (in
+particular, parameter subtypes of a formal subprogram), but I can't seem to
+construct an example.
+
+...
+> This could be somehow generalized so that the "X + 1"
+> expression in the above example (in the instance, not in the
+> generic) is statically unevaluated.
+>
+> I say wait until someone complains about this one.
+
+I was just thinking that your mind was leaving you again... :-)
+
+One side thought:
+Even if we don't formally adopt a rule saying that there is no recheck here, in
+the absence of an ACATS test I wouldn't expect there to be any recheck here.
+That's because these rechecks usually take explicit work, and in the absence of
+some reminder (either a bug report or an ACATS test), it is rare that they get
+implemented. In Janus/Ada specifically, we have to write explicit code for any
+rechecks needed. A lot of the time when implementing a new legality rule, we
+forgot to handle the recheck (and a good part of the time, no recheck is needed,
+which makes even less likely to think of it the next time). Moreover, a lot of
+those rechecks require saving information that otherwise would be discarded
+(like the exact contents of a default expression in a generic - since we code
+share, these have already been code generated and thus have no need -- other
+than rechecks -- to be saved).
+
+The net effect is that I suspect that this "recheck" will hardly ever be
+implemented (especially as no bug can result from omitting it). That seems like
+the best reason for actually making an explicit exception in this case: the
+recheck will take a lot of work to implement.
+
+****************************************************************
Questions? Ask the ACAA Technical Agent