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

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

--- ai12s/ai12-0401-1.txt	2020/10/22 23:59:00	1.2
+++ ai12s/ai12-0401-1.txt	2020/12/04 07:59:30	1.3
@@ -1,7 +1,9 @@
-!standard 3.3(23.2/3)                                    20-10-21  AI12-0401-1/02
+!standard 3.3(23.2/3)                                    20-10-29  AI12-0401-1/03
 !standard 8.5.1(4.7/5)
+!standard 8.5.1(5/3)
 !class binding interpretation 20-10-15
 !status Amendment 1-2012 20-10-21
+!status work item 20-10-29
 !status ARG Approved 13-0-1  20-10-21
 !status work item 20-10-15
 !status received 20-10-15
@@ -40,6 +42,10 @@
 
 !wording
 
+[Editor's note: This wording is found in draft 27 of the RM, even though it is
+not yet approved. I had already added the wording when the additional issues 
+were detected, and I didn't want the RM to reflect known bad wording.]
+
 Modify 3.3(23.2/3)
   [to ensure known-to-be-constrained is not influenced by the nominal
    subtype of the qualified_expression]
@@ -48,14 +54,45 @@
     partial view{, and it is neither a value conversion nor a
     qualified_expression}; or
 
+Delete 8.5.1(4.7/5) [moved below]
+
 Add after 8.5.1(4.7/5):
   
-  In the case where the /object_/name is a qualified_expression whose
-  expression is a name that denotes a variable, the nominal subtype of
-  the [Redundant:(constant)] view denoted by the qualified_expression
-  shall statically match the nominal subtype of that variable, or
-  statically match either the base subtype of its type if scalar, or the
-  first subtype of its type otherwise.
+  In the case where the /object_/name is a qualified_expression with 
+  a nominal subtype S and whose expression is a name that denotes an 
+  object Q:
+     * if S is an elementary subtype, then:
+        * Q shall be a constant other than a dereference of an access type; or
+        * the nominal subtype of Q shall be statically compatible with S; or
+        * S shall statically match the base subtype of its type if scalar, or 
+          the first subtype of its type if an access type.
+     * if S is a composite subtype, then Q shall be known to be constrained or
+       S shall statically match the first subtype of its type.
+
+     AARM Ramification: There's no restriction if the expression is a value.
+
+     AARM Reason: This check prevents the renamed object from violating its
+     nominal subtype. As the subtype is only checked when the object is renamed,
+     we make it illegal if the actual object is a variable whose value could be 
+     changed afterwards to violate the subtype. This is messy as "known to be 
+     constrained" is only defined for composite objects, so we have to handle 
+     elementary objects and all values separately.
+
+
+Modify 8.5.1(5/3):
+
+  The renamed entity shall not be a subcomponent that depends on 
+  discriminants of an object whose nominal subtype is unconstrained unless 
+  the object is known to be constrained. A slice of an array shall not be 
+  renamed if this restriction disallows renaming of the array. [In 
+  addition to the places where Legality Rules normally apply, these rules 
+  apply also in the private part of an instance of a generic unit.]
+
+  In addition to the places where Legality Rules normally apply (see 12.3),
+  these rules also apply in the private part of an instance of a generic unit.
+
+  AARM Discussion: This applies to all of the Legality Rules in this 
+  subclause.
 
 !discussion
 
@@ -87,13 +124,23 @@
 
 !example
 
-In the situation mentioned in the !problem:
+In a situation analogous to the one mentioned in the !problem:
 
-   X : T := ...;
-   Y : S renames S'(X);
+   X : Integer := ...;
+   Y : Positive renames Positive'(X);
+   
+This renaming will be illegal since Positive statically matches neither 
+Integer nor Integer'Base.  That is good, because in the following we would 
+have trouble because the nominal subtype of Y is the static subtype Positive, 
+so without this rule, the following case statement would be legal:
+
+   X := -1;
+   case Y of
+      when 1 .. Positive'Last => 
+         pragma Assert (Y > 0);
+   end case;
    
-The renaming will be illegal unless S statically matches T, T'Base (if
-scalar), or the first subtype of T (if nonscalar).
+even though the case choices do not cover all of the possible values of Y.
 
 !corrigendum 3.3(23.2/3)
 
@@ -110,12 +157,36 @@
 In addition to the places where Legality Rules normally apply (see 12.3), this
 rule applies also in the private part of an instance of a generic unit.>
 @dinst
-In the case where the @i<object_>@fa<name> is a @fa<qualified_expression> whose
-@fa<expression> is a @fa<name> that denotes a variable, the nominal subtype of
-the (constant) view denoted by the @fa<qualified_expression> shall statically 
-match the nominal subtype of that variable, or statically match either the 
-base subtype of its type if scalar, or the first subtype of its type otherwise.
+In the case where the @i<object_>@fa<name> is a @fa<qualified_expression> with
+a nominal subtype @i<S> and whose @fa<expression> is a @fa<name> that denotes an 
+object @i<Q>:
+
+@xbullet<if @i<S> is an elementary subtype, then:>
+@xinbull<@i<Q> shall be a constant other than a dereference of an access type; or>
+@xinbull<the nominal subtype of @i<Q> shall be statically compatible with @i<S>; or>
+@xinbull<@i<S> shall statically match the base subtype of its type if scalar, or 
+the first subtype of its type if an access type.>
+@xbullet<if @i<S> is a composite subtype, then @i<Q> shall be known to be 
+constrained or @i<S> shall statically match the first subtype of its type.>
 
+!corrigendum 8.5.1(5/3)
+
+@drepl
+The renamed entity shall not be a subcomponent that depends on discriminants 
+of an object whose nominal subtype is unconstrained unless the object is known 
+to be constrained. A @fa<slice> of an array shall not be renamed if this restriction
+disallows renaming of the array. In addition to the places where Legality Rules
+normally apply, these rules apply also in the private part of an instance of a 
+generic unit.
+@dby
+The renamed entity shall not be a subcomponent that depends on discriminants 
+of an object whose nominal subtype is unconstrained unless the object is known
+to be constrained. A @fa<slice> of an array shall not be renamed if this restriction
+disallows renaming of the array.
+
+In addition to the places where Legality Rules normally apply (see 12.3), these 
+rules also apply in the private part of an instance of a generic unit.
+
 !ASIS
 
 No ASIS effect.
@@ -131,5 +202,377 @@
 of qualified expressions as names in Ada 2012. It seems to me that it
 should apply to Ada 2012 as well, even if that is (very) marginally
 incompatible.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, October 21, 2020  3:55 PM
+
+Below is the example I promised for AI12-0401-1 about renaming a qualified 
+expression.
+
+------------------
+
+!example
+
+In a situation analogous to the one mentioned in the !problem:
+
+   X : Integer := ...;
+   Y : Positive renames Positive'(X);
+   
+This renaming will be illegal since Positive statically matches neither 
+Integer nor Integer'Base.  That is good, because in the following we would 
+have trouble because the nominal subtype of Y is the static subtype Positive, 
+so without this rule, the following case statement would be legal:
+
+   X := -1;
+   case Y is
+      when 1 .. Positive'Last => 
+         pragma Assert (Y > 0);
+   end case;
+   
+even though the case choices do not cover all of the possible values of Y.
+
+****************************************************************
+
+From: Jeff Cousins
+Sent: Thursday, October 22, 2020  1:10 PM
+
+> case Y of
+ 
+case Y is
+
+methinks!
+
+> Y : Positive renames Positive'(X);
+ 
+
+Is this currently legal ?  GNAT only seems to allow renaming of an object, 
+not of a qualified expression.
+
+>  case Y {is}[of]
+
+Wouldn’t the compiler require case alternatives for all values of X anyway, 
+not just of Y, as renaming doesn’t require subtype conformance ?  As stated 
+in the !problem of AI12-0275, “the constraints ... of the subtype_mark are 
+ignored in favor of those of the renamed object”, so any constraints in the 
+subtype of Y are irrelevant, and indeed given AI12-0275 the subtype mark no 
+longer even has to be given in the renaming ?
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, October 22, 2020  1:48 PM
+
+>>  case Y of
+ 
+>case Y is
+> 
+>methinks!
+
+Youthinks right!
+ 
+>> Y : Positive renames Positive'(X);
+ 
+>Is this currently legal ?  GNAT only seems to allow renaming of an object, 
+>not of a qualified expression.
+
+GNAT apparently never implemented this feature.
+
+>>  case Y {is}[of]
+ 
+>Wouldn’t the compiler require case alternatives for all values of X anyway, 
+>not just of Y, as renaming doesn’t require subtype conformance ?  As stated 
+>in the !problem of AI12-0275, “the constraints ... of the subtype_mark are 
+>ignored in favor of those of the renamed object”, so any constraints in the 
+>subtype of Y are irrelevant, and indeed given AI12-0275 the subtype mark no 
+>longer even has to be given in the renaming ?
+
+That's all true, but in the sentence you quoted, the "renamed object" is 
+"Positive'(X)" which has nominal subtype Positive.  We could have written 
+"Y : Natural renames Positive'(X);" and Y would still have the nominal subtype 
+Positive.  Unfortunately, X has the nominal subtype Integer, so we can set X 
+to a negative value while the rename of it exists, and the renaming has the 
+nominal subtype Positive.
+
+****************************************************************
+
+From: Jeff Cousins
+Sent: Thursday, October 22, 2020  3:41 PM
+
+Thanks Tuck.
+
+>>>  case Y {is}[of]
+
+>> Wouldn’t the compiler require case alternatives for all values of X anyway, 
+>> not just of Y, as renaming doesn’t require subtype conformance ?  As stated 
+>> in the !problem of AI12-0275, “the constraints ... of the subtype_mark are 
+>> ignored in favor of those of the renamed object”, so any constraints in the
+>> subtype of Y are irrelevant, and indeed given AI12-0275 the subtype mark no
+>> longer even has to be given in the renaming ?
+
+>That's all true, but in the sentence you quoted, the "renamed object" is 
+>"Positive'(X)" which has nominal subtype Positive.  We could have written 
+>"Y : Natural renames Positive'(X);" and Y would still have the nominal 
+>subtype Positive.  Unfortunately, X has the nominal subtype Integer, so we 
+>can set X to a negative value while the rename of it exists, and the renaming 
+>has the nominal subtype Positive.
+
+Whether Y is Natural or Positive, does it actually matter ?
+
+The compiler will check that there are case alternatives for all possible 
+values of the subtype of X, regardless of whatever the subtype of Y is: 
+Positive, Natural, or anything else.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, October 22, 2020  4:59 PM
+
+> The compiler will check that there are case alternatives for all possible 
+> values of the subtype of X, regardless of whatever the subtype of Y is: 
+> Positive, Natural, or anything else.
+
+You seem to have faith that the compiler will do the "right thing" but the 
+RM says that you only need case alternatives to cover the nominal subtype (if
+it is static -- see 5.4(7/4)), hence why we are focusing on the question of 
+what is the nominal subtype of the renaming of a qualified_expression.
+
+For reference, the wording of 5.4(7/4) is:
+
+  "If the selecting_expression is a name [(including a type_conversion, 
+   qualified_expression, or function_call)] having a static and constrained 
+   nominal subtype, then each non-others discrete_choice shall cover only 
+   values in that subtype that satisfy its predicates (see 3.2.4), and each 
+   value of that subtype that satisfies its predicates shall be covered by 
+   some discrete_choice [(either explicitly or by others)]."
+
+That "static and constrained nominal subtype" phrase is the key one.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, October 22, 2020  7:10 PM
+
+>> Y : Positive renames Positive'(X);
+
+>Is this currently legal ?  GNAT only seems to allow renaming of an 
+>object, not of a qualified expression.
+
+Yes, that's legal Ada 2012. (It would be legal in Ada 202x even without the 
+qualification change, since one can now rename values.)
+
+I guess the C-Test for this AI needs a higher priority than I originally 
+assigned it. ;-) The B-Test has a rather high priority since it represents 
+an incompatibility with Ada 2012, the C-Test is lower since it doesn't seem 
+to be a particularly important capability.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, October 22, 2020  7:26 PM
+
+...
+> You seem to have faith that the compiler will do the "right thing" but 
+> the RM says that you only need case alternatives to cover the nominal 
+> subtype (if it is static -- see 5.4(7/4)), hence why we are focusing 
+> on the question of what is the nominal subtype of the renaming of a 
+> qualified_expression.
+
+Yup.
+
+One thing that may not be clear is why renames are different from other uses
+of qualified_expressions. The reason for that is that the subtype check is 
+performed at the point that the qualified_expression is evaluated.
+
+So if you had directly written:
+
+   X := -1;
+   case Positive'(X) is
+      when 1 .. Positive'Last => 
+         pragma Assert (Y > 0);
+   end case;
+
+The qualified expression will perform a check that X is in Positive (which 
+will fail, of course), so there is no problem with the case statement not 
+having choices for negative numbers. (Indeed, choices for negative numbers 
+would be illegal in this case statement -- they're out of the range of the 
+nominal subtype of the expression.)
+
+However, for a renames, the check is performed when the renames is evaluated, 
+and is never repeated. That's why we need restrictions on what can be renamed 
+(Ada 83 has such rules for discriminant-dependent components, so this was 
+always intended). Otherwise, one would need to repeat the checks at every use, 
+and that was clearly not the model intended by Ada 83 (renaming was intended 
+in part to improve efficiency by avoiding re-evaluation of expensive names), 
+and certainly is not something that compilers could support without quite a 
+bit of extra work.
+
+Hope this helps.
+
+****************************************************************
+
+From: Jeff Cousins
+Sent: Friday, October 23, 2020  3:07 AM
+
+Thanks Tuck and Randy for your replies.
+
+>You seem to have faith that the compiler will do the "right thing" but the 
+>RM says that you only need case alternatives to cover the nominal subtype 
+>(if it is static -- see 5.4(7/4)), hence why we are focusing on the question
+>of what is the nominal subtype of the renaming of a qualified_expression.
+> 
+>For reference, the wording of 5.4(7/4) is:
+> 
+>"If the selecting_expression is a name [(including a type_conversion, 
+>qualified_expression, or function_call)] having a static and constrained 
+>nominal subtype, then each non-others discrete_choice shall cover only values
+>in that subtype that satisfy its predicates (see 3.2.4), and each value of 
+>that subtype that satisfies its predicates shall be covered by some 
+>discrete_choice [(either explicitly or by others)]."
+> 
+>That "static and constrained nominal subtype" phrase is the key one.
+ 
+Sorry to labour the point, but isn’t it the subtype of X that matters, not 
+the subtype of Y?
+
+Otherwise, how do you square this with the !problem of AI12-027 saying, 
+“the constraints ... of the subtype_mark are ignored in favor of those of
+the renamed object”
+
+procedure Test_401 is
+   subtype My_Subtype          is Integer range 3 .. 5;
+   subtype Garbage_Subtype is Integer range -19 .. -7;
+   X : My_Subtype;
+   Y : Garbage_Subtype renames X;
+begin
+   X := 3;
+   case Y is
+      when 3 .. 5 => 
+         pragma Assert (Y in 3 .. 5);
+   end case;
+end Test_401;
+
+Clean compiles.  The compiler is clearly using the subtype of X not subtype 
+of Y when checking the case statement.
+
+The subtype of Y is virtually irrelevant, that’s why AI12-0275 makes it 
+optional.
+
+****************************************************************
+
+From: Arnaud Charlet
+Sent: Friday, October 23, 2020  3:48 AM
+
+> > Is this currently legal ?  GNAT only seems to allow renaming of an object,
+> > not of a qualified expression.
+> 
+> GNAT apparently never implemented this feature.
+
+You guys are either using an old version of GNAT (for Jeff, which is expected 
+since Jeff is no longer a customer), or didn't bother to check with a current 
+GNAT.
+
+The latest GNAT Pro (which is the only version with reasonable support for Ada 
+202x and therefore relevant in such discussions) supports the above construct 
+with -gnat2020 and will yield:
+
+$ gcc -c p.ads -gnat2020 -gnatl
+
+     1. package P is
+     2.
+     3.    X : Natural := 0;
+     4.    Y : Positive renames Positive'(X);
+                                        |
+        >>> warning: value not in range of type "Standard.Positive"
+        >>> warning: "Constraint_Error" will be raised at run time
+
+     5.
+     6. end P;
+
+FWIW if you compile without -gnat2020 you'll get:
+
+$ gcc -c p.ads
+p.ads:4:33: warning: value not in range of type "Standard.Positive"
+p.ads:4:33: warning: "Constraint_Error" will be raised at run time
+p.ads:4:33: value in renaming requires -gnat2020
+
+So yes, this was legal in Ada 202x up to AI12-0401 and will now become illegal.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Friday, October 23, 2020  7:19 AM
+
+>Sorry to labour the point, but isn’t it the subtype of X that matters, not 
+>the subtype of Y? Otherwise, how do you square this with the !problem of 
+>AI12-027 saying, “the constraints ... of the subtype_mark are ignored in 
+>favor of those of the renamed object”
+
+The "renamed object" is the qualified expression, since that is what is 
+denoted by the object_name in the object renaming.  It is true that the 
+subtype specified for the renaming is irrelevant, but the subtype specified
+in the qualified expression is *not* irrelevant.  It determines the nominal 
+subtype of the renamed object.  And that is what we are worried about.
+ 
+>procedure Test_401 is
+>   subtype My_Subtype          is Integer range 3 .. 5;
+>   subtype Garbage_Subtype is Integer range -19 .. -7;
+>   X : My_Subtype;
+>   Y : Garbage_Subtype renames X;
+>begin
+>   X := 3;
+>   case Y is
+>      when 3 .. 5 => 
+>         pragma Assert (Y in 3 .. 5);
+>   end case;
+>end Test_401;
+> 
+>Clean compiles.  The compiler is clearly using the subtype of X not subtype 
+>of Y when checking the case statement. The subtype of Y is virtually 
+>irrelevant, that’s why AI12-0275 makes it optional.
+
+Yes, but the above is not a renaming of a qualified expression.  That is the 
+only case we are talking about in this entire thread.  If you change this to:
+
+   Y : Garbage_Subtype renames Bizarro_Subtype'(X);
+
+then in "case Y is" what will matter is the range of Bizarro_Subtype, even 
+though X might be changed to be outside the Bizarro_Subtype.
+
+****************************************************************
+
+From: Jeff Cousins
+Sent: Friday, October 23, 2020  7:38 AM
+
+Many thanks Tuck, that makes more sense.
+
+****************************************************************
+
+
+Summary of private discussion, October 22-25, 2020
+
+A number of issues are missed by the approved wording:
+
+(1) The rules should be after paragraph 4.7 rather than 4, in order to
+put the rules closer to similar requirements and to avoid renumbering existing
+paragraphs.
+
+(2) "variable" isn't the only cases that cause problems. The "known to be
+constrained" rules encapulate those cases for composite types; for elementary
+types, it would be enough to require a constant other than a dereference of
+an access type (an access-to-constant can designate a variable).
+
+(3) We don't want to make more cases illegal than necessary as this is an
+incompatibility and a potential annoyance. As such, we should use "static
+compatibility" for elementary types (the "known to be constrained" rules
+do that for composite types).
+
+(4) The generic boilerplate should apply to these new rules. Rather than
+duplicating it, we make it apply to all of the Legality Rules in this 
+subclause. (The paragraph 4 and 4.1-4.3 rules probably don't need it, but it
+is harmless for them.)
+
+We have reopened the AI to allow the ARG to review the updated wording.
 
 ****************************************************************

Questions? Ask the ACAA Technical Agent