CVS difference for ai05s/ai05-0220-1.txt
--- ai05s/ai05-0220-1.txt 2010/06/13 07:18:24 1.1
+++ ai05s/ai05-0220-1.txt 2010/08/05 01:11:52 1.2
@@ -1,14 +1,14 @@
-!standard 4.3.1(17) 10-06-13 AI05-0220-1/00
+!standard 4.3.1(17) 10-08-04 AI05-0220-1/01
!class binding interpretation 10-06-13
!status work item 10-06-13
!status received 10-03-16
!priority Low
!difficulty Easy
-!qualifier Omission
+!qualifier Clarification
!subject Definition of "needed component"
!summary
-*** TBD ***
+Staticness requirements clarified for record aggregate discriminants.
!question
@@ -50,7 +50,7 @@
In this case, there are no components in the variant part, so it hard to
see how 4.3.1(17) applies. But it seems needlessly complex to require the
existence of components to make this check. Should this aggregate be
-rejected?
+rejected? (Yes.)
Similarly:
@@ -75,22 +75,93 @@
Variant_Record_3' (Disc => Two, Disc2 => Function_Call, F => 2.0);
Here, Disc2 is dynamic, but it is known to not control a variant since Disc
-is statically known to be Two. Should this aggregate be rejected?
+is statically known to be Two. Should this aggregate be rejected? (No.)
!recommendation
-(See Summary.)
+(See Wording.)
!wording
-** TBD **
+Replace 4.3.1(17)
+ If the components of a variant_part are needed, then the value of a
+ discriminant that governs the variant_part shall be given by a static
+ expression.
+
+with
+
+ The value of a discriminant that governs a variant_part P
+ shall be given by a static expression, unless P is nested within
+ a variant V that is not selected by the discriminant value
+ governing the variant_part enclosing V.
+
!discussion
-** TBD **
+The existing wording is quite clear that it applies only when there are actually
+components. However, as the questioner points out, this makes little sense
+since it makes the interpretation of the rule dependent on discriminant values
+that aren't necessarily known when this rule is enforced. Essentially, the rule is
+circular in that it depends on itself in order to be understandable.
+
+Thus we adopt a rule that does not depend on components that are "needed". For
+this new rule, the variants of the variant_part P mentioned in the wording play
+no role. In particular, it makes no difference whether the variant_part P
+contains no component_declararations.
+
+This interpretation is technically an incompatibility, as aggregates containing
+a variant_part with no components controlled by a dynamic discriminant are now
+rejected, while with the old rule these appear to be legal. This incompatibility
+would be rare in practice. Moreover, a survey of existing compilers show that
+all reported (GNAT, Irvine, AdaMagic, Janus/Ada) actually do not consider
+whether a variant has components in enforcing 4.3.1(17). Thus, the
+incompatibility does not exist in practice (compilers already reject such
+programs).
+
+Note that wording following "unless" exists to allow the last example of the
+!question to remain legal. This is necessary to avoid an unnecessary
+incompatibility: 3 out of 4 existing compilers currently allow this example.
+There seems to be no important reason to change this result.
+
+Finally, the following example was illegal before this change and remains
+illegal:
+
+ type T1 (D1 : Boolean) is
+ tagged record
+ case D1 is
+ when False =>
+ C : Character;
+ ...
+ when True =>
+ S : String(1..10);
+ ...
+ end case;
+ end record;
+
+ type T2 (D2 : Integer) is new T1 (D1 => Some_Non_Static_Value)
+ with ...;
+
+ X2 : T2 := (D2 => 123, ....); -- Illegal
+
+In this case, the offending non-static discriminant value for D1 does not occur
+within the aggregate, but the rule still applies and the aggregate is illegal.
+
+!corrigendum 4.3.1(17)
+
+@drepl
+If the components of a @fa<variant_part> are needed, then the value of a
+discriminant that governs the @fa<variant_part> shall be given by a static
+expression.
+@dby
+The value of a discriminant that governs a @fa<variant_part> @i<P>
+shall be given by a static expression, unless @i<P> is nested within
+a @fa<variant> @i<V> that is not selected by the discriminant value
+governing the @fa<variant_part> enclosing @i<V>.
!ACATS Test
+Add an additional ACATS B-Test to check that the corner cases clarified by this
+AI (see the !appendix for part of a possible test).
!appendix
@@ -218,3 +289,624 @@
the enclosing variant_part.
****************************************************************
+
+From: Steve Baird
+Sent: Monday, August 2, 2010 6:52 PM
+
+Randy and I have been discussing solving the problem identified in this AI by
+replacing 4.3.1(17)
+
+ If the components of a variant_part are needed, then the value of a
+ discriminant that governs the variant_part shall be given by a static
+ expression.
+
+with something along the lines of
+
+ If the value of a discriminant that governs a variant_part
+ determines which components are needed, then the value of that
+ discriminant shall be given by a static expression. The variants of
+ the given variant_part play no role in determining the applicability
+ of this rule.
+
+ AARM note:
+ For example, a variant_part which contains no component_declarations
+ in any of its variants is treated the same (with respect to this rule)
+ as a variant_part which contains component_declarations.
+
+The second sentence is intended to clarify the meaning of he word "determines"
+in the first sentence. We don't want to have to worry about oddball corner cases
+where one could argue that a nonstatic discriminant might be allowed.
+
+On the other hand, it seems important that we do allow a non-static discriminant
+to govern a nested variant part in the case where the (static) discriminant
+value governing an enclosing variant_part did not select the enclosing variant
+of the variant_part in question.
+
+The above wording is intended to accomplish this and is hoped to be just a
+confirmation of existing practice for implementations. This has been confirmed
+for the GNAT compiler.
+
+This AI is not intended to make work for implementers. The goal is to define the
+"nobody cares" corner cases in a way that is consistent with existing common
+practice. The test given below can be used to check whether an existing
+implementation already implements the proposed rule. Randy reports that the
+Janus compiler rejects the 4 aggregates marked "ERROR", but also rejects the
+aggregate marked "legal". Results from other compilers could be useful in
+evaluating this proposal.
+
+Comments?
+
+ -- Steve
+
+=====
+
+ procedure Corner_Cases (Non_Static : Boolean) is
+
+ type T1 (D : Boolean) is
+ record
+ case D is
+ when False => null;
+ when True => null;
+ end case;
+ end record;
+
+ X1 : T1 := (D => Non_Static); -- ERROR
+
+ type T2 (D : Boolean) is
+ record
+ case D is
+ when Boolean => null;
+ end case;
+ end record;
+
+ X2 : T2 := (D => Non_Static); -- ERROR
+
+ type T3 (D : Natural) is
+ record
+ case D is
+ when Natural => null;
+ when others => Unlikely : Float;
+ end case;
+ end record;
+
+ X3 : T3 := (D => Boolean'Pos (Non_Static)); -- ERROR
+
+ type T4 (D1, D2 : Boolean) is
+ record
+ case D1 is
+ when False => null;
+ when True =>
+ case D2 is
+ when False => null;
+ when True => Int : Integer;
+ end case;
+ end case;
+ end record;
+
+ X4_A : T4 := (D1 => Non_Static, D2 => False); -- ERROR
+ X4_B : T4 := (D1 => False, D2 => Non_Static); -- legal
+
+ begin
+ null;
+ end Corner_Cases;
+
+****************************************************************
+
+From: Dan Eilers
+Sent: Monday, August 2, 2010 7:05 PM
+
+> Randy reports that the Janus compiler
+> rejects the 4 aggregates marked "ERROR", but also rejects the
+> aggregate marked "legal". Results from other compilers could be useful
+> in evaluating this proposal.
+
+Our compiler rejects the 4 aggregates marked "ERROR", and accepts the one marked
+"legal".
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, August 2, 2010 7:22 PM
+
+I don't find the second sentence as being very helpful. Better might be to put
+it into the AARM note and make the AARM note more explicit.
+
+I wonder whether it might be better to make the following incremental wording
+change:
+
+ If the components of a variant_part are needed, {even if
+ there are none,} then the value of a discriminant that
+ governs the variant_part shall be given by a static
+ expression.
+
+I don't think your rewording really solves the problem anyway, since if all
+variant alternatives are "null" then you are back to the situation where there
+are no components, so the value of the discriminant might be thought to be
+irrelevant depending on the interpretation. I suppose your second sentence was
+supposed to clarify, but it really didn't help me at all.
+
+For the record, the AdaMagic front end complains about the aggregates just as
+you predicted in your "Corner_Cases" example, so with my vendor hat on, I
+support the proposed "interpretation" of this rule that you have suggested.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Tuesday, August 3, 2010 12:44 PM
+
+> I don't find the second sentence as being very helpful. Better might
+> be to put it into the AARM note and make the AARM note more explicit.
+
+Would it be better if we spell things out more explicitly?
+
+ The value of a discriminant that governs a variant_part shall be
+ given by a static expression, unless
+ - the variant_part occurs within an enclosing (not necessarily
+ immediately enclosing) variant_part; and
+ - the variant enclosing the enclosed variant_part is not
+ selected by the discriminant value governing the enclosing
+ variant_part.
+
+If it seems necessary, we could add another item in the middle
+of that bulleted list:
+
+ - the value of the discriminant that governs the enclosing
+ variant_part is given by static expression; and
+
+I don't think this is necessary.
+
+The problem I see with this approach is illustrated by the
+following example:
+
+ type T1 (D1 : Boolean) is
+ record
+ case D1 is
+ when False => null;
+ when True => Int : Integer;
+ end case;
+ end record;
+
+ type T2 (D2 : Boolean) is new T1 (D1 => Some_Non_Static_Value)
+ with null record;
+
+ X : T2 := (D2 => False); -- must be illegal
+
+It is not clear (at least to me) that the wording I've proposed
+above covers this case. We want to reject this because the
+variant_part in T1 (or perhaps the inherited copy thereof in T2,
+although the RM never speaks of inheriting a variant_part)
+is governed by Some_Non_Static_Value, an expression which doesn't
+even occur in the aggregate.
+
+The original wording handled this case by making use of the
+term "needed".
+
+I suppose we could adopt a belt-and-suspenders approach, modifying
+the wording suggested above by replacing
+
+ The value of a discriminant that governs a variant_part shall be
+ given by a static expression, unless
+
+with
+
+ The value of a discriminant that governs a variant_part whose
+ components are needed shall be given by a static expression, unless
+
+and then adding an AARM note to confirm that the phrase
+"whose components are needed" does indeed apply to a
+componentless variant_part.
+
+This seems clunky, but I don't see an elegant solution.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, August 3, 2010 1:00 PM
+
+I guess I still prefer the wording I proposed:
+
+ If the components of a variant_part are needed, {even if
+ there are none,} then the value of a discriminant that
+ governs the variant_part shall be given by a static
+ expression.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Tuesday, August 3, 2010 1:46 PM
+
+It seems to me that any rule that starts with
+
+ If the components of a variant_part have some property,
+ even if there are none, then ...
+
+would, based on a strict reading, apply uniformly to all componentless
+variant_parts.
+
+We want this rule to apply to some componentless variant_parts but not to
+others, depending on whether the components of the variant_part would have been
+needed if only the variant_part had components.
+
+I don't think the wording you've suggested accomplishes this, at least if it is
+read strictly.
+
+On the other hand, this point is fairly pedantic.
+
+I could live with the wording that you suggest if we add AARM text (preferably a
+"To Be Honest" note) to clarify what is really meant.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, August 3, 2010 2:08 PM
+
+Given that this is a corner case, I am reluctant to add a bunch of words to the
+RM. Adding words to clarify things in the AARM is fine with me. Apparently all
+of the implementors interpreted this the same way, and as far as I know no
+"real" user has complained about this, so going overboard in an RM explanation
+seems a waste of everyone's energy.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, August 3, 2010 2:15 PM
+
+How about:
+
+ If the components of a variant_part are needed, {even if
+ there are none *in the chosen variant*,} then the value of
+ a discriminant that governs the variant_part shall be
+ given by a static expression.
+
+This make the extra phrase somewhat more useful even in a non-corner case where
+some but not all of the variants of the variant part have components. To cover
+the silly case where none of the variants have components, we can add a "to be
+honest".
+
+****************************************************************
+
+From: Steve Baird
+Sent: Tuesday, August 3, 2010 2:46 PM
+
+My first reaction was to agree with your analysis and view this as an
+improvement.
+
+On the other hand, it seems that we are introducing a circularity in talking
+about "the chosen variant" in the legality rule which is, in turn, needed to
+ensure that "the chosen variant" is well defined. At the very least, this is
+potentially confusing.
+
+Given this, I don't think this addition would be an improvement.
+It's a close call (for me) and, as before, I could live with this as long as the
+AARM tells the full story.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, August 3, 2010 4:10 PM
+
+...
+> It seems to me that any rule that starts with
+>
+> If the components of a variant_part have some property,
+> even if there are none, then ...
+>
+> would, based on a strict reading, apply uniformly to all componentless
+> variant_parts.
+
+Isn't that what we want?
+
+> We want this rule to apply to some componentless variant_parts but not
+> to others, depending on whether the components of the variant_part
+> would have been needed if only the variant_part had components.
+
+I can't parse this at all. Could you remind me which of the corner case(s) you
+are concerned about here?
+
+> I don't think the wording you've suggested accomplishes this, at least
+> if it is read strictly.
+>
+> On the other hand, this point is fairly pedantic.
+
+It's beyond pedantic, it defies understanding. ;-)
+
+> I could live with the wording that you suggest if we add AARM text
+> (preferably a "To Be Honest" note) to clarify what is really meant.
+
+I guess I'd like to know what is really meant before agreeing or disagreeing
+with this.
+
+Steve later says:
+
+>> How about:
+>>
+>> If the components of a variant_part are needed, {even if
+>> there are none *in the chosen variant*,} then the value of
+>> a discriminant that governs the variant_part shall be
+>> given by a static expression.
+>
+...
+>On the other hand, it seems that we are introducing a circularity in talking
+>about "the chosen variant" in the legality rule which is, in turn, needed to
+>ensure that "the chosen variant" is well defined. At the very least, this is
+>potentially confusing.
+
+Doesn't this logic apply to any wording containing "needed" as well? After all,
+it is the discriminant values that determine what components are needed
+(especially in nested variants). Adam's original complaint about this wording
+was the circularity of "needed" and this rule.
+
+The fact that no one actually implements the rule as written was something that
+Steve and I realized while we were discussing fixes to Adam's original
+complaint.
+
+I agree that everyone seems to have interpreted this the same (with a slight
+difference in Janus/Ada), but that doesn't address the wording confusion that
+Adam pointed out. So I think I prefer Steve's earlier proposal, as it doesn't
+suffer from this circularity.
+
+Indeed, I would prefer to simply say:
+
+ The value of a discriminant that governs a variant_part shall be
+ given by a static expression.
+
+since no one has explained to me why there is any value to allowing a non-static
+discriminant that controls an unselected variant. At a minimum, that seems to be
+a design problem (using a single discriminant for multiple purposes); if it is
+simply a "don't care" discriminant (which I would hope), why would using a
+static discriminant be a hardship??
+
+But I realize that this would introduce an incompatibility (of the best kind
+- detected at compile-time), so I suppose we need the extra wording:
+
+ The value of a discriminant that governs a variant_part shall be
+ given by a static expression, unless the variant_part V occurs within an
+ enclosing (not necessarily immediately enclosing) variant_part E and
+ the variant enclosing V is not selected by the discriminant value
+ governing E.
+
+(I introduced the names "V" and "E" to clearly mark which variant_part is which
+in this wording -- there are just too many "enclosing"s in Steve's original
+wording; once done, the bullets didn't seem necessary. I considered not
+introducing "E", it doesn't help as much as "V" does, but I went with the
+shortest wording.)
+
+****************************************************************
+
+From: Steve Baird
+Sent: Tuesday, August 3, 2010 4:27 PM
+
+> ...
+>> It seems to me that any rule that starts with
+>>
+>> If the components of a variant_part have some property,
+>> even if there are none, then ...
+>>
+>> would, based on a strict reading, apply uniformly to all
+>> componentless variant_parts.
+>
+> Isn't that what we want?
+>
+
+No.
+
+>> We want this rule to apply to some componentless variant_parts but
+>> not to others, depending on whether the components of the
+>> variant_part would have been needed if only the variant_part had
+>> components.
+>
+> I can't parse this at all. Could you remind me which of the corner
+> case(s) you are concerned about here?
+>
+
+ type T4 (D1, D2 : Boolean) is
+ record
+ case D1 is
+ when False => null;
+ when True =>
+ case D2 is
+ when False => null;
+ when True => Int : Integer;
+ end case;
+ end case;
+ end record;
+
+ X4_B : T4 := (D1 => False, D2 => Non_Static); -- legal
+
+We want the above aggregate to be legal. If the rule applied to every
+veriant_part, then it would be rejected.
+
+> Indeed, I would prefer to simply say:
+>
+> The value of a discriminant that governs a variant_part shall be
+> given by a static expression.
+
+That rule would be consistent with what Janus implements and would cause the
+X4_B aggregate above to be rejected.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Tuesday, August 3, 2010 4:43 PM
+
+> Doesn't this logic apply to any wording containing "needed" as well?
+> After all, it is the discriminant values that determine what
+> components are needed (especially in nested variants). Adam's original
+> complaint about this wording was the circularity of "needed" and this rule.
+
+Yes, you are right. That circularity seems to have been granted a "grandfather"
+clause on the grounds that a really correct rule requires too much RM wording.
+That doesn't necessarily mean that we want to introduce another circularity, but
+I'd agree that it weakens the argument against adding another one.
+
+> But I realize that this would introduce an incompatibility (of the
+> best kind
+> - detected at compile-time), so I suppose we need the extra wording:
+>
+> The value of a discriminant that governs a variant_part shall be
+> given by a static expression, unless the variant_part V occurs within an
+> enclosing (not necessarily immediately enclosing) variant_part E and
+> the variant enclosing V is not selected by the discriminant value
+> governing E.
+
+If you drop the use of "needed", then how do you handle things like
+
+ type T1 (D1 : Boolean) is
+ tagged record
+ case D1 is
+ when False => null;
+ when True => Int : Integer;
+ end case;
+ end record;
+
+ type T2 (D2 : Integer) is new T1 (Some_Non_Static_Value)
+ with null record;
+
+ X2 : T2 := (D2 => 123); -- must be illegal
+
+In this case, the problematic non-static discriminant value does not occur in
+the aggregate. With the wording you've suggested, it sounds like we iterate over
+the discriminants in the aggregate, but that's not good enough in the above
+case. The current wording handles this by use of the word "needed".
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, August 3, 2010 4:59 PM
+
+> In this case, the problematic non-static discriminant value does not
+> occur in the aggregate. With the wording you've suggested, it sounds
+> like we iterate over the discriminants in the aggregate, but that's
+> not good enough in the above case. The current wording handles this by
+> use of the word "needed".
+
+I *don't* handle anything; you are the one that suggested this wording (I just
+cleaned it up to eliminate the feeling that this was "a lot of new wording".
+
+But I don't even see the problem that you are complaining about here. You
+carefully worded this so that it says "the discriminant that governs a variant
+part" -- it makes no requirement that that discriminant appears in the
+aggregate! (I recall us discussing this in the past.) I would say that an AARM
+note to point this out (that the discriminant could be given in a derivation
+only and not appear in the aggregate) would be sufficient.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Tuesday, August 3, 2010 5:24 PM
+
+You're right. This AI is making me punchy.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, August 3, 2010 4:36 PM
+
+[Editor's note: This message appears to be a reply to Steve's message of
+2:46 PM, but no message was quoted.]
+
+OK, how about:
+
+ If the components of a variant_part are needed {(even if
+ there are no components in some of its variants)},
+ then the value of a discriminant that governs the variant_part
+ shall be given by a static expression.
+
+I really hate to see this definition get a lot longer.
+By parenthesizing hopefully we reduce even further the need for the casual user
+to worry about it.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Tuesday, August 3, 2010 5:17 PM
+
+> OK, how about:
+>
+> If the components of a variant_part are needed {(even if
+> there are no components in some of its variants)},
+> then the value of a discriminant that governs the variant_part
+> shall be given by a static expression.
+
+I can live with any of the recent alternatives you've suggested (with an
+accompanying AARM explanation).
+
+I don't feel strongly about it.
+
+> I really hate to see this definition get a lot longer.
+I think everyone is agreed on that point.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, August 3, 2010 4:51 PM
+
+> OK, how about:
+>
+> If the components of a variant_part are needed {(even if
+> there are no components in some of its variants)},
+> then the value of a discriminant that governs the variant_part
+> shall be given by a static expression.
+>
+> I really hate to see this definition get a lot longer.
+> By parenthesizing hopefully we reduce even further the need for the
+> casual user to worry about it.
+
+I still object to using "needed" in this wording, as it is not well-defined
+until after this rule is applied. (That is, if the discriminants are non-static,
+how do you figure out if a component or variant is needed?? We don't want to go
+there.)
+
+I agree about making this definition "a lot longer", but the proposed rewording
+I suggested is not a lot longer.
+
+ The value of a discriminant that governs a variant_part shall be
+ given by a static expression, unless the variant_part V occurs within an
+ enclosing (not necessarily immediately enclosing) variant_part E and
+ the variant enclosing V is not selected by the discriminant value
+ governing E.
+
+Resorting to word counts, Tucker's wording has 36 words; my rewording (of
+Steve's older proposal) has 44 words (or 22% larger). 22% is not a lot in RM
+terms!!
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, August 3, 2010 5:12 PM
+
+Or shorter:
+
+ The value of a discriminant that governs a variant_part P
+ shall be given by a static expression, unless P is nested within
+ a variant V that is not selected by the discriminant value
+ governing the variant_part enclosing V.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Tuesday, August 3, 2010 5:20 PM
+
+I like it.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, August 3, 2010 5:32 PM
+
+Goody: 38 words, only 5% larger. ;-)
+
+P.S. Looks OK to me.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, August 3, 2010 5:34 PM
+
+> You're right. This AI is making me punchy.
+
+Well, all you have to do now is write it up, using Tucker's rewrite of my
+rewrite of your older proposed wording.
+
+****************************************************************
+
Questions? Ask the ACAA Technical Agent