Open yannickmoy opened 3 years ago
Thanks for submitting this one @yannickmoy ! I have had this issue as well a few times in the past. Here are some thoughts:
Specifically for the generic issue, could we have a way in Ada to specify that a generic parameter needs to be static? e.g.
generic
Gen_Size : Integer with Static;
package Z is
type T is range 0 .. 5 with Size => Gen_Size;
end Z;
with regards to (Payload'Size / U32'Size) * U32'Size, isn't that a static expression? (so maybe we should also allow static expressions)?
@QuentinOchem the ability to specify that a generic parameter is static seems different from this issue. And T'Size is a static expression only when T is a static scalar subtype, see http://www.ada-auth.org/standards/2xrm/html/RM-4-9.html
A colleague pointed out that one can use Pack and Component_Size on type Arr, which is sufficient for the compiler to compute the Size of the type (at least if the implementation advice of Ada RM 13.3(73) is followed, which is the case in GNAT).
But this is not possible if array Arr (or a record) contains elements whose type is defined by a formal parameter of the generic. In that case, we'd like to express Component_Size again in terms of non-static expressions according to the Ada RM, which is rejected.
Thus, it seems worthwhile to make it possible to express all such representative clauses/aspects for Size/Object_Size/Component_Size/Alignment more liberally in a generic, provided the expression is statically known in the instance. This might be easier to do in a generic spec than in a generic body, according to Ada RM 12.3(11):
In a generic unit, Legality Rules are enforced at compile time of the generic_declaration and generic body, given the properties of the formals. In the visible part and formal part of an instance, Legality Rules are enforced at compile time of the generic_instantiation, given the properties of the actuals. In other parts of an instance, Legality Rules are not enforced; this rule does not apply when a given rule explicitly specifies otherwise.
This allows rules where we assume the best in a generic spec (because instance rechecking acts as a safety net if an optimistic guess turns out to be wrong) and conservatively assume the worst in a generic body (because there is no instance rechecking).
Summary
Currently, Ada only allows specifying the Size/Object_Size/Alignment of types with static values. This makes it impossible to specify them in generics when they refer to values from formal parameters. So the following code is rejected:
Even without generics, Ada only allows specifying static values for Size/Object_Size/Alignment. This makes it impossible to compute such a value based on the Size/Object_Size/Alignment of other types. So the following code is also rejected:
Motivation
Infrastructure software needs sometimes to interpret data through different types, without copying it. This can be done by overlaying a variable on top of another one, specifying the address of one for the other, like in the examples above. Given that the type system of Ada does not guard against reading too little or too much data here, it would be safer to specify the intended Size/Object_Size/Alignment of the overlay. This is also needed for the SPARK tool to be able to verify statically that the overlay does not allow reading past the overlaid object.
Caveats and alternatives
The alternative if to not specify the representation attributes of such types, and let the compiler decide, but check them with the GNAT-specific pragma
Compile_Time_Assert
, as in:Note that the semantics of this pragma are subtle, as it's not guaranteed to fail at compilation if the compiler frontend cannot determine statically the value of the expression. The SPARK tool takes a stricter approach and issues a message if it cannot determine that the expression is always False. This would be the outcome currently (a message from SPARK tool), but possibly the tool could be modified to link that kind of assertions with the corresponding type, as a kind of heuristic replacement for the corresponding representation aspect or clause.