Version 1.1 of acs/ac-00260.txt

Unformatted version of acs/ac-00260.txt version 1.1
Other versions for file acs/ac-00260.txt

!standard 4.9(2-13)          14-05-09 AC95-00260/00
!class Amendment 13-05-09
!status received no action 14-05-09
!status received 14-04-16
!subject Why isn't 'Size static?
!summary
!appendix

!topic Why isn't 'Size static?
!reference RM12 4.9(2-13)
!from Adam Beneschan 14-04-16
!discussion

Is there any reason why T'Size shouldn't be a static expression, if T is a
definite type?  I'm running into problems trying to do something like

    type T_As_Bits is mod 2**T'Size;

where T is either a definite private type, or an access type.  The rules in
4.9(2-13) don't appear to allow this, but I don't see a good reason why.

There may be other representation-related attributes which logically should be
static also (like 'Position, 'First_Bit, 'Stream_Size on an access type).

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

From: Randy Brukardt
Sent: Thursday, April 17, 2014  12:08 AM

> Is there any reason why T'Size shouldn't be a static expression, if T
> is a definite type?

Of course. Defining exactly what cases allow it to be static would be rather
complicated. "Definite" surely isn't enough, since a subtype with a dynamic
constraint is still definite. Given that implementations can use non-contiguous
representations for composite types, we'd probably want to exclude some
additional kinds of subtypes (perhaps all types with discriminant-dependent
components?). And of course, any component that has a non-static 'Size (by
whatever definition we came up with) should prevent the enclosing composite
object from having a static size (how could one add two non-static sizes and end
up with something static?). That's probably more complication than any of the
language design teams wanted to wrestle with.

Luckily, you didn't ask if there was a *good* reason! :-)

> I'm running into
> problems trying to do something like
>
>     type T_As_Bits is mod 2**T'Size;
>
> where T is either a definite private type, or an access type.
>  The rules in 4.9(2-13) don't appear to allow this, but I don't see a
> good reason why.

Oh, now you went and did ask about a good reason. Can't help you there. :-)

I've run into this as well, but a quick look at the complications involved (it
would pretty much require new line items in 4.9 for each specific attribute we
wanted to allow) dampened my enthusiasm.

As far as the actual problem goes, usually it turns out that T has a Size clause
of some kind (or should have one for portability). In that case, I take the
expression of the Size clause and make a constant out of it. Then I can use that
in both places (the Size aspect and in the later type declaration). Sometimes
I've had to do that recursively (if T'Size uses C'Size). The result is usually
just as readable and no more likely to get broken by future maintenance, so
given that the workaround isn't usually much worse than the original code, it's
hard to get excited about the nasty work of defining T'Size as static in some
proper way (other than the scalar and string cases, which already can be
static).

For example:

    type T ...
        with Size => <expr>;
    type T_as_Bits is mod 2**T'Size;

becomes:

    Size_of_T : constant := <expr>;
    type T ...
        with Size => Size_of_T;
    type T_as_Bits is mod 2**Size_of_T;

> There may be other representation-related attributes which logically
> should be static also (like 'Position, 'First_Bit, 'Stream_Size on an
> access type).

Probably, but as each would have to be a case-by-case basis (you forgot
'Alignment, BTW), it seems that the unpleasantness would multiply.

I suppose if enough people make noise, we might get more ambitious. The squeaky
wheel gets the grease, after all. :-)

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

From: Bob Duff
Sent: Thursday, April 17, 2014  10:42 AM

> Luckily, you didn't ask if there was a *good* reason! :-)

I agree with your reasons, and I think they're good ones.

In addition:

Allowing it for private types would break privacy.
Clearly T'Size can't be static (for clients):

    package P is
        type T is private;
    private
        type T is array (1..Read_From_Keyboard) of ...;
    end P;

Unlike many ARG members, I am not 100% opposed to breaking privacy.
But I'm at least 99% opposed.

Also, many compilers do record layout and the like in the back end.  But static
values need to be known to the front end. So allowing it would be an earthquake
for those compilers. As Randy showed, it's a minor inconvenience to programmers,
which is not worth any earthquakes.

> work of defining T'Size as static in some proper way (other than the
> scalar and string cases, which already can be static).

String_Subtype'Size is never static.

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

From: Adam Beneschan
Sent: Thursday, April 17, 2014  11:10 AM

> > Luckily, you didn't ask if there was a *good* reason! :-)
>
> I agree with your reasons, and I think they're good ones.
>
> In addition:
>
> Allowing it for private types would break privacy.
> Clearly T'Size can't be static (for clients):
>
>     package P is
>         type T is private;
>     private
>         type T is array (1..Read_From_Keyboard) of ...;
>     end P;

For some reason I didn't think of this case.  It does pretty much make the whole
idea impossible.  Unless we were to add a new aspect that would prevent the
completion from being an unknown size:

     package P is
         type T is private with Definite_Size;
     private
            -- the aspect would make this illegal
         type T is array (1..Read_From_Keyboard) of ...;
     end P;

So it's possible in theory to provide for a feature like this, but it would be a
lot of work, and the problem case I ran into was quite specialized and something
I'd expect others to run into very rarely. So I'm sure it wouldn't be
worthwhile.  Anyway, I was able to work around my particular problem.

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

From: Jeffrey Carter
Sent: Thursday, April 17, 2014  1:29 PM

To the non-language-lawyer user, it seems reasonable for 'Size to be static for

Scalar types
Access types
Constrained array types with static index constraints and a component
type having static 'Size
Non-discriminated record types with all components having static 'Size

> Also, many compilers do record layout and the like in the back end.
> But static values need to be known to the front end.
> So allowing it would be an earthquake for those compilers.

In light of this, maybe record types are not so reasonable after all.

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

From: Tucker Taft
Sent: Thursday, April 17, 2014  4:44 PM

> To the non-language-lawyer user, it seems reasonable for 'Size to be
> static for
>
> Scalar types
> Access types
> Constrained array types with static index constraints and a component
> type having static 'Size

I would probably agree with these, and also perhaps make a special case for
System.Address ;-) to avoid the kludge of having to use
System.Storage_Elements.Integer_Address'Size.

One issue with arrays is packed vs. unpacked.  Packing might also be a backend
thing for some compilers.  Given that, it might be better to just stick with
scalars and access types.  You can always specify 'Component_Size if you want on
an array, and then do the multiplication yourself with some confidence.

> Non-discriminated record types with all components having static 'Size

For the reason stated below, record types are probably not feasible.

>> Also, many compilers do record layout and the like in the back end.
>> But static values need to be known to the front end.
>> So allowing it would be an earthquake for those compilers.
>
> In light of this, maybe record types are not so reasonable after all.

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


Questions? Ask the ACAA Technical Agent