Version 1.2 of acs/ac-00231.txt

Unformatted version of acs/ac-00231.txt version 1.2
Other versions for file acs/ac-00231.txt

!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.

***************************************************************

From: Robert Dewar
Sent: Sunday, February 26, 2012  12:45 PM

I think this is definitely too late for Ada 2012, as has been pointed out, there
are some subtleties here, and it may be harder than it looks to allow this
without unintended consequences. So this should be for Ada 2020.

***************************************************************

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.

***************************************************************

From: Robert Dewar
Sent: Sunday, February 26, 2012  12:45 PM

I think this is definitely too late for Ada 2012, as has been pointed out, there
are some subtleties here, and it may be harder than it looks to allow this
without unintended consequences. So this should be for Ada 2020.

***************************************************************

From: Jeff Cousins
Sent: Monday, February 27, 2012  9:32 AM

That's what I meant by an Ada 2012 AI rather than an Ada 2005 AI - one on Ada
2012 for consideration for Ada 2012.

***************************************************************

From: Robert Dewar
Sent: Monday, February 27, 2012  10:14 AM

And I am saying it is too late for Ada 2012, which at this stage is essentially
complete as of the Florida meeting, with no more substantive changes expected.
This is a substantive change that should be considered for the next version, but
not Ada 2012.

***************************************************************

From: Tucker Taft
Sent: Monday, February 27, 2012  11:02 AM

I am pretty sure Jeff meant to write "on Ada2012 for consideration for Ada2020."

***************************************************************

From: Robert Dewar
Sent: Monday, February 27, 2012  11:23 AM

Ah yes, that makes sense :-)

***************************************************************

From: Jeff Cousins
Sent: Tuesday, February 28, 2012  8:59 AM

Yes, that's what my brain had thought it had told my fingers but I must have
been too tired to succeed!

***************************************************************

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).

It's also true that this design dates to Ada 83 and has never been changed.
If there was a real problem, it would have showed up in the Ada 9x comments,
the Ada 200x comments, or somewhere else. No one has said that they've
definitely run into this in practice.

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.

***************************************************************


Questions? Ask the ACAA Technical Agent