8.5.1 Object Renaming Declarations
Syntax
Name Resolution Rules
Reason: A
previous version of Ada 9X used the usual “expected type”
wording:
“The expected type for the
object_name
is that determined by the
subtype_mark.”
We changed it so that this would be illegal:
X: T;
Y: T'Class renames X; -- Illegal!
When the above
was legal, it was unclear whether Y was of type T or T'Class. Note that
we still allow this:
Z: T'Class := ...;
W: T renames F(Z);
where F is a function with a controlling parameter
and result. This is admittedly a bit odd.
Note that the matching rule for generic formal
parameters of mode in out was changed to keep it consistent with
the rule for renaming. That makes the rule different for in vs.
in out.
Legality Rules
The renamed entity shall be an object.
{
AI95-00231-01}
{
AI95-00409-01}
shall both be access-to-object types with statically matching designated
subtypes and with both or neither being access-to-constant types; or
{statically matching (required) [partial]}
{
AI95-00409-01}
shall both be access-to-subprogram types with subtype conformant designated
profiles.
{subtype conformance (required)}
if the
object_name
denotes a generic formal object of a generic unit
G, and the
object_renaming_declaration
occurs within the body of
G or within the body of a generic unit
declared within the declarative region of
G, then the declaration
of the formal object of
G shall have a
null_exclusion;
otherwise, the subtype of the
object_name
shall exclude null.
{generic contract
issue [partial]} 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.
Reason: This
rule prevents “lying”.
Null must never be the value
of an object with an explicit
null_exclusion.
The first bullet is an assume-the-worst rule which prevents trouble in
one obscure case:
type Acc_I is access Integer;
subtype Acc_NN_I is not null Acc_I;
Obj : Acc_I := null;
generic
B : in out Acc_NN_I;
package Gen is
...
end Gen;
package body Gen is
D : not null Acc_I renames B;
end Gen;
package Inst is new Gen (B => Obj);
Without the first bullet rule, D would be legal,
and contain the value null, because the rule about lying is satisfied
for generic matching (Obj matches B; B does not explicitly state not
null), Legality Rules are not rechecked in the body of any instance,
and the template passes the lying rule as well. The rule is so complex
because it has to apply to formals used in bodies of child generics as
well as in the bodies of generics.
{
8652/0017}
{
AI95-00184-01}
{
AI95-00363-01}
The renamed entity shall not be a subcomponent that depends on discriminants
of a variable whose nominal subtype is unconstrained, unless this subtype
is indefinite, or the variable is constrained by its initial value. 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. These rules also apply for a renaming that appears in the
body of a generic unit, with the additional requirement that even if
the nominal subtype of the variable is indefinite, its type shall not
be a descendant of an untagged generic formal derived type.
Reason: This prevents renaming of subcomponents
that might disappear, which might leave dangling references. Similar
restrictions exist for the Access attribute.
{
8652/0017}
{
AI95-00184-01}
The “recheck on instantiation” and “assume-the-worst
in the body” restrictions on generics are necessary to avoid renaming
of components which could disappear even when the nominal subtype would
prevent the problem:
type T1 (D1 : Boolean) is
record
case D1 is
when False =>
C1 : Integer;
when True =>
null;
end case;
end record;
generic
type F is new T1;
X : in out F;
package G is
C1_Ren : Integer renames X.C1;
end G;
type T2 (D2 : Boolean := False) is new T1 (D1 => D2);
Y : T2;
package I is new G (T2, Y);
Y := (D1 => True); -- Oops! What happened to I.C1_Ren?
Implementation Note: Note that if an
implementation chooses to deallocate-then-reallocate on
assignment_statements
assigning to unconstrained definite objects, then it cannot represent
renamings and access values as simple addresses, because the above rule
does not apply to all components of such an object.
Ramification: If it is a generic formal
object, then the assume-the-best or assume-the-worst rules are applied
as appropriate.
To be honest: {
AI95-00363-01}
If renamed entity is a subcomponent that depends on discriminants, and
the subcomponent is a dereference of a general access type whose designated
type is unconstrained and whose discriminants have defaults, the renaming
is illegal. Such a general access type can designate an unconstrained
(stack) object. Since such a type might not designate an object constrained
by its initial value, the renaming is illegal — the rule says “is”
constrained by its initial value, not “might be” constrained
by its initial value. No other interpretation makes sense, as we can't
have legality depending on something (which object is designated) that
is not known at compile-time, and we surely can't allow this for unconstrained
objects. The wording of the rule should be much clearer on this point,
but this was discovered after the completion of Amendment 1 when it was
too late to fix it.
Static Semantics
Discussion: Because the constraints are
ignored, it is a good idea to use the nominal subtype of the renamed
object when writing an
object_renaming_declaration.
{
AI95-00409-01}
If no
null_exclusion
is given in the renaming, the object may or may not exclude null. This
is similar to the way that constraints need not match, and
constant
is not specified. The renaming defines a view of the renamed entity,
inheriting the original properties.
Examples
Example of renaming
an object:
declare
L : Person
renames Leftmost_Person; --
see 3.10.1
begin
L.Age := L.Age + 1;
end;
Wording Changes from Ada 83
The phrase “subtype ... as defined in
a corresponding object declaration, component declaration, or component
subtype indication,” from RM83-8.5(5), is incorrect in Ada 95;
therefore we removed it. It is incorrect in the case of an object with
an indefinite unconstrained nominal subtype.
Incompatibilities With Ada 95
{
AI95-00363-01}
{
incompatibilities with Ada 95}
Aliased variables
are not necessarily constrained in Ada 2005 (see
3.6).
Therefore, a subcomponent of an aliased variable may disappear or change
shape, and renaming such a subcomponent thus is illegal, while the same
operation would have been legal in Ada 95. Note that most allocated objects
are still constrained by their initial value (see
4.8),
and thus have no change in the legality of renaming for them. For example,
using the type T2 of the previous example:
AT2 : aliased T2;
C1_Ren : Integer renames AT2.C1; -- Illegal in Ada 2005, legal in Ada 95
AT2 := (D1 => True); -- Raised Constraint_Error in Ada 95,
-- but does not in Ada 2005, so C1_Ren becomes
-- invalid when this is assigned.
Extensions to Ada 95
{
AI95-00230-01}
{
AI95-00231-01}
{
AI95-00254-01}
{
AI95-00409-01}
{
extensions to Ada 95}
A renaming can have
an anonymous access type. In that case, the accessibility of the renaming
is that of the original object (accessibility is not lost as it is for
a component or stand-alone object).
Wording Changes from Ada 95
{
8652/0017}
{
AI95-00184-01}
Corrigendum: Fixed to forbid renamings of depends-on-discriminant
components if the type
might be definite.