!standard 6.5(2.1/2) 12-05-01 AC95-00231/00 !class Amendment 12-05-01 !status received no action 12-05-01 !status received 12-02-12 !subject Using 'Range in type declarations !summary !appendix From: Bob Duff Sent: Sunday, February 12, 2012 10:09 AM Robert asked me to send this. Is the following legal? package Typ_Is_Range is S : constant String := "abc"; type T is range S'Range; end Typ_Is_Range; If it said, "type T is range S'First..S'Last;", it would clearly be legal. RM-3.5 says: 14 S'Range S'Range is equivalent to the range S'First .. S'Last. But we normally interpret "equivalent" as a semantic equivalence; it doesn't change the grammar, which does NOT allow an attribute reference: > 3.5.4: > signed_integer_type_definition ::= range > static_simple_expression .. static_simple_expression (Note that that "range" is the reserved word. I misread it as the nonterminal range, and imagined a "|" that's not there, until Robert corrected me.) *************************************************************** From: Robert Dewar Sent: Sunday, February 12, 2012 10:14 AM to me, this is a clear oddity, and I would change the grammar to say: 3.5.4 SIGNED_INTEGER_TYPE_DEFINITION ::= range static_RANGE *************************************************************** From: Robert Dewar Sent: Sunday, February 12, 2012 10:19 AM I really tnink "is equivalent" NEVER refers to syntax. Just look through the uses of "is equivalent" in the RM, you get into deep trouhble if you interpet this as syntactic equivalence, e.g. "-"(Left, Right) is equivalent to "and"(Left, "not"(Right)) Bur that's not true at the syntactic level, because you might have redefined "not"! That's just the first example I picked at random, there are many others. *************************************************************** From: Bob Duff Sent: Sunday, February 12, 2012 10:27 AM > to me, this is a clear oddity, and I would change the grammar to say: > > 3.5.4 > SIGNED_INTEGER_TYPE_DEFINITION ::= range static_RANGE ^^^^^ ^^^^^^ ^^^^^ ||||| |||||| ||||| bold italic nonterminal-font I prefer to leave it alone. Yes, it's an oddity, but not worth fixing, IMHO. I'm not sure, but I suspect the above simple fix is wrong, because there are probably all sorts of rules that apply to the nonterminal RANGE that should not apply to SIGNED_INTEGER_TYPE_DEFINITION's. Sounds like hours of work for ARG. [Editor's note: The obvious difference is that the types of the two operands need not be the same, unlike a normal range (see 3.5.4(5)). That's a pretty big difference, IMHO, and it would make this harder to define.] *************************************************************** From: Robert Dewar Sent: Sunday, February 12, 2012 10:31 AM > I prefer to leave it alone. Yes, it's an oddity, but not worth > fixing, IMHO. Fine with me, easier for me to make the corresponding bug report dead than fix it! Though actually I think I may give a specific error message given that this violates expectations :-) *************************************************************** From: Robert Dewar Sent: Sunday, February 12, 2012 12:44 PM Well I don't see an RM reference as being useful here, since the RM has nothing further to add to the message. We only add RM references when the RM adds something useful. There is no point in sending people to the RM and wasting their time. If it is some language expert who does not believe the error message, that's their problem :-) But a clearer message would help ... so that's what I did: > 1. package Typ_Is_Range is > 2. S : constant String := "abc"; > 3. type T is range S'Range; > | > >>> Range attribute not allowed here, use First .. Last > > 4. end Typ_Is_Range; *************************************************************** From: Robert Dewar Sent: Sunday, February 12, 2012 1:49 PM For the record, there is an ACATS test b35401b that makes sure that you give an error message in this situation. *************************************************************** From: Dan Eilers Sent: Sunday, February 12, 2012 11:01 PM I am in favor of fixing this language bug. These sorts of inconsistencies in the easy-to-understand parts of the language give Ada a bad name. Here's an expanded example: package Typ_Is_Range is S : constant String := "abc"; type T1 is range S'Range; -- should be OK type T2 is range S'First .. S'Last; -- OK type T3 is new integer range S'range; -- OK type T4 is new integer range S'First..S'Last; -- OK subtype T5 is integer range S'range; -- OK subtype T6 is integer range S'First..S'Last; -- OK end Typ_Is_Range; I am also in favor of fixing the following language bug regarding staticness of ranges, which is perhaps somewhat related. package bad is s: string(1..3) := "abcde"; -- currently legal but should be illegal a: array (1..2, 1..3) of integer := (1..3 => (1..2 => 0)); -- ditto end bad; *************************************************************** From: Robert Dewar Sent: Sunday, February 12, 2012 11:32 PM >> to me, this is a clear oddity, and I would change the grammar to say: >> >> 3.5.4 >> SIGNED_INTEGER_TYPE_DEFINITION ::= range static_RANGE > > I am in favor of fixing this language bug. These sorts of > inconsistencies in the easy-to-understand parts of the language give Ada a bad > name. Well I thought that at first, but am now convinced this is insufficiently broken. No one has complained in 20 years, and this was still not something noticed externally, but rather by someone at AdaCore. Furthermore, giving the clearer error message affects only one test in our giant test suite, namely the ACATS test that specifically tests that this case is illegal. And as Bob notes, fixing it may not be so trivial > I am also in favor of fixing the following language bug regarding > staticness of ranges, which is perhaps somewhat related. > > package bad is > s: string(1..3) := "abcde"; -- currently legal but should be illegal > a: array (1..2, 1..3) of integer := (1..3 => (1..2 => 0)); -- ditto > end bad; I don't think that's a bug, and I don't think it should be "fixed". A warning (which any decent compiler will give) is good enough here. *************************************************************** From: Dan Eilers Sent: Monday, February 13, 2012 12:44 AM > And as Bob notes, fixing it may not be so trivial yes, things often are harder to fix than they first look, but there's no evidence here that this is any harder than applying the equivalence that a'range = a'first .. a'last. > No one has complained in 20 years, I'm not sure that the lack of complaints indicates much. Users don't normally complain to a compiler vendor about such things, they just figure out the workaround, grumble, and move on. > > package bad is > > s: string(1..3) := "abcde"; -- currently legal but should be illegal > > a: array (1..2, 1..3) of integer := (1..3 => (1..2 => 0)); -- ditto > > end bad; > > I don't think that's a bug, and I don't think it should be "fixed". > A warning (which any decent compiler will give) is good enough here. Can you explain why a language known for early detection of errors, and used in safety-critical applications should allow stuffing 5 characters into a 3-character string, or swapping the dimensions of an aggregate? I've seen the aggregate case happen. Warnings are a necessary evil when there is a high likelihood of false positives, or when detecting the condition is beyond the capabilities of some compilers. But that isn't the case here. *************************************************************** From: Robert Dewar Sent: Monday, February 13, 2012 6:30 AM >> No one has complained in 20 years, > > I'm not sure that the lack of complaints indicates much. > Users don't normally complain to a compiler vendor about such things, > they just figure out the workaround, grumble, and move on. Actually that's definitely not true for us, almost all our users contact us if they find anything to grumble about, it would be very unusual if one of our users encountered something puzzling like this and did not raise the issue with us. No, I think it is more that this is a very unusual construct. If you have type R is range S'First .. S'Last; it is much more natural to write type R is new S; *************************************************************** From: Jeff Cousins Sent: Monday, February 13, 2012 8:40 AM But S is an object not a type so you can't compile type R is new S. Say a programmer is given a string that he needs to manipulate type My_String_Type is new String (1..3); My_String : My_String_Type := "abc"; He thinks "I'll need an index for accessing the data. Ooh, I know, I'll use this clever 'Range attribute they taught me on the course" type String_Index_Type is range My_String'Range; String_Index: String_Index_Type; This promptly fails to compile. If he'd thought ahead it might have been better for him to have written type String_Index_Type is range 1..3; type My_String_Type is new String (String_Index_Type); My_String : My_String_Type := "abc"; String_Index: String_Index_Type; but My_String_Type and My_String could be someone else's code in some legacy package that he doesn't want to touch. *************************************************************** From: Tucker Taft Sent: Monday, February 13, 2012 8:54 AM type String_Index_Type is range My_String'First .. My_String'Last; String_Index : String_Index_Type; should work fine. *************************************************************** From: Jeff Cousins Sent: Monday, February 13, 2012 9:29 AM Yes that compiles and is what people use, but intuitively a programmer would expect type String_Index_Type is range My_String'Range; String_Index: String_Index_Type; to work. *************************************************************** From: Bob Duff Sent: Monday, February 13, 2012 9:19 AM > > type String_Index_Type is range 1..3; type My_String_Type is new > > String (String_Index_Type); That's illegal. The index type of String is Integer. > > My_String : My_String_Type := "abc"; > > String_Index: String_Index_Type; > > > > but My_String_Type and My_String could be someone else's code in some > > legacy package that he doesn't want to touch. > > type String_Index_Type is range My_String'First .. My_String'Last; > String_Index : String_Index_Type; > > should work fine. I don't see how it can work. It's a new type, so cannot be used to index into My_String. If "is range My_String'Range" were allowed, it would have the same problem. The only thing that makes sense is: SUBtype String_Index_Type is Positive range My_String'Range; *************************************************************** From: Bob Duff Sent: Monday, February 13, 2012 9:11 AM > > And as Bob notes, fixing it may not be so trivial > > yes, things often are harder to fix than they first look, but there's > no evidence here that this is any harder than applying the equivalence > that a'range = a'first .. a'last. When the RM says "equivalent", it doesn't mean at the syntax level. The equivalence is semantic. So if you want to allow "type T is range Blah'Range;" then the syntax rules have to be changed. I'm not 100% opposed to that, but if you want to push it, I suggest you propose exact wording changes. I just don't think it's important enough to expend any time on. This is hardly the most glaring wart in the language. > > No one has complained in 20 years, > > I'm not sure that the lack of complaints indicates much. > Users don't normally complain to a compiler vendor about such things, > they just figure out the workaround, grumble, and move on. > > > > package bad is > > > s: string(1..3) := "abcde"; -- currently legal but should be illegal > > > a: array (1..2, 1..3) of integer := (1..3 => (1..2 => 0)); -- ditto > > > end bad; > > > > I don't think that's a bug, and I don't think it should be "fixed". > > A warning (which any decent compiler will give) is good enough here. > > Can you explain why a language known for early detection of errors, > and used in safety-critical applications should allow stuffing 5 > characters into a 3-character string, or swapping the dimensions of an > aggregate? I've seen the aggregate case happen. This is really a separate issue, so you should have sent it as a separate email, to ease Randy's job of filing the emails. (Maybe we could automate the filing process!) Anyway, there are many places where run-time errors can be caught at compile time. The general style of Ada is to call them run-time errors, and hope that compilers warn when possible. If you propose to fix that in general, it's WAY too much work. If you propose to fix the two examples you showed, then what's the point -- it doesn't fix the general problem. Without an exact wording-change proposal, I can't tell which you are proposing, or maybe something in between. *************************************************************** From: Jeff Cousins Sent: Monday, February 13, 2012 5:26 AM >> No one has complained in 20 years, > I'm not sure that the lack of complaints indicates much. > Users don't normally complain to a compiler vendor about such things, they just figure out the workaround, grumble, and move on. I think many users in my company hit this problem when we first started using Ada 20+ years ago, probably the first error they'd hit where Ada was behaving un-intuitively rather than something that at a second look was obviously a coding error. (The restrictions on membership tests that AI-158 is fixing might have been second). On the other hand we've learnt to live with it and no one is jumping up and down about it. *************************************************************** From: Robert Dewar Sent: Monday, February 13, 2012 1:05 PM > Yes that compiles and is what people use, but intuitively a programmer > would expect type String_Index_Type is range My_String'Range; > String_Index: String_Index_Type; > to work. Well once again, this never came up in 20 years. it has always been illegal to use 'Range (and this is verified by an ACATS test), so I still don't think it's sufficiently wrong to change. But of course it is trivial in the implementation to change it (I would just remove the error message :-)) *************************************************************** From: Jeff Cousins Sent: Sunday, February 26, 2012 12:34 PM Could we have an Ada 2012 AI on this, please? It seems anomalous to allow A'Range as a shorthand for A'First .. A'Last in most places but not for integer type declarations. *************************************************************** Editor's Note: This topic was tabled for lack of support. Note that no one has ever shown a realistic example where this would be a remotely useful idea (the example Jeff showed being illegal because the type would be wrong; a subtype needs to be used in that context and would be needed in similar contexts). In addition, there is no "equivalence" here, as the expr .. expr of an integer type declaration is *not* a range; the expressions have special resolution rules and need not be of the same type. Plus, this same construct also appears in floating point and fixed point type declarations; these would also need changes (it would be idiotic to change only the integer case when the float and fixed cases are the same. This would be substantial work in both language wording and in compiler implementation ('Range being unlike any other language construct, it has to be handled specially by a compiler). Given the lack of viable examples, it would be silly to put in that effort when it could be used for something valuable. ***************************************************************