Version 1.1 of ai05s/ai05-0220-1.txt
!standard 4.3.1(17) 10-06-13 AI05-0220-1/00
!class binding interpretation 10-06-13
!status work item 10-06-13
!status received 10-03-16
!priority Low
!difficulty Easy
!qualifier Omission
!subject Definition of "needed component"
!summary
*** TBD ***
!question
Consider:
type Enum is (One, Two, Three);
type Variant_Record (Disc : Enum) is record
case Disc is
when One =>
I : Integer;
when Two =>
F : Float;
when Three =>
null;
end case;
end record;
Variant_Part' (Disc => Function_Call(Param));
4.3.1(9) says that the components that are "needed" are determined by the
"composite value"; that depends on the discriminant values.
The discriminant values can be determined at runtime; in this case the
needed components are not known until runtime. But "needed" components
participate in Legality Rules and clearly need to be known at compile-time.
4.3.1(17) attempts to require a static discriminant value, but it depends
on the definition of "needed". Thus, one could argue that the aggregate
above is legal if Function_Call returns Three. That is obviously nonsense,
but exactly where is the line drawn? If we have:
type Variant_Record_2 (Disc : Enum) is record
case Disc is
when others => null;
end case;
end record;
R : Variant_Record_2 := (Disc => Some_Function_Call);
In this case, there are no components in the variant part, so it hard to
see how 4.3.1(17) applies. But it seems needlessly complex to require the
existence of components to make this check. Should this aggregate be
rejected?
Similarly:
type Enum is (One, Two, Three);
type Variant_Record_3 (Disc : Enum; Disc2 : Boolean) is record
case Disc is
when One =>
I : Integer;
case Disc2 is
when True =>
J : Integer;
when False =>
null;
end case;
when Two =>
F : Float;
when Three =>
null;
end case;
end record;
Variant_Record_3' (Disc => Two, Disc2 => Function_Call, F => 2.0);
Here, Disc2 is dynamic, but it is known to not control a variant since Disc
is statically known to be Two. Should this aggregate be rejected?
!recommendation
(See Summary.)
!wording
** TBD **
!discussion
** TBD **
!ACATS Test
!appendix
!topic Definition of "needed component"
!reference 4.3.1
!from Adam Beneschan 10-03-16
!discussion
While looking over the record aggregate rules when responding to a recent
comp.lang.ada post, it occurred to me that the rules regarding components in
variant parts might be incorrect.
Consider:
type Enum is (One, Two, Three);
type Variant_Record (Disc : Enum) is record
case Disc is
when One =>
I : Integer;
when Two =>
F : Float;
when Three =>
null;
end case;
end record;
For a record_aggregate of type Variant_Record, 4.3.1(9) says that "all
copmonents of the value defined by the aggregate are needed". This means that
the "needed components" depend on the value of the discriminant (and 9.a in the
AARM says so explicitly). Thus, for example, in (Disc => One, I => 5), F is not
needed, and for (Disc => Three), neither I nor F is needed.
4.3.1(17) says, "If the components of a variant part are needed, then the value
of a discriminant that governs the variant_part shall be given by a static
expression". But, by 4.3.1(9), whether "the components of a variant part are
needed" depends on the actual value of the discriminant, and thus can't be
determined statically. So in this case:
Variant_Part' (Disc => Function_Call(Param));
If the function returns Three, then 4.3.1(17) wouldn't apply, since no
components of a variant part are needed, and thus the aggregate would be legal.
This can't make sense---certainly, the legality of the aggregate can't depend on
what the function is going to return at runtime!
So I think 4.3.1(17) is worded incorrectly. Maybe it can be solved by defining
the concept of a variant_part being "needed"; change 4.3.1(9) to:
For the record_component_association_list of a record_aggregate, all components
of the composite value defined by the aggregate are needed; for the association
list of an extension_aggregate, only those components not determined by the
ancestor expression or subtype are needed (see 4.3.2). For the
record_component_association_list of a record_aggregate, if the aggregate's type
has a variant_part, then that variant_part is needed; for the association list
of an extension_aggregate, variant_parts that are part of the aggregate's type,
and that are not part of a record type that is an ancestor of the ancestor
expression's type or of the ancestor subtype, are needed. Each selector_name in
..."
and then change 4.3.1(17) to "If a variant_part is needed, then the value of a
discriminant that governs the variant_part shall be given by a static
expression".
Note: GNAT rejects this, which I think is correct:
type Variant_Record_2 (Disc : Enum) is record
case Disc is
when others => null;
end case;
end record;
R : Variant_Record_2 := (Disc => <something-nonstatic>);
but one could argue from the rules as currently written that this should be
legal since there is no possibility that a component in a variant part would be
"needed". If the *intent* is for this to be legal, then my proposed change
would be an incompatibility. I'm sort of guessing that this isn't a problem.
****************************************************************
From: Adam Beneschan
Sent: Thursday, March 18, 2010 10:40 PM
I realized this morning that this isn't quite correct and would introduce an
incompatibility. In this case:
type Enum is (One, Two, Three);
type Variant_Record (Disc : Enum; Disc2 : Boolean) is record
case Disc is
when One =>
I : Integer;
case Disc2 is
when True =>
J : Integer;
when False =>
null;
end case;
when Two =>
F : Float;
when Three =>
null;
end case;
end record;
the aggregate
Variant_Record' (Disc => Two, Disc2 => B, F => 2.0);
should be legal even if B is nonstatic; since Disc is statically determined to
be Two, the variant part governed by Disc2 isn't used. But the way I worded it,
the variant_part governed by Disc2 would still be "needed", because it's there.
So another sentence should be added to my proposed wording:
For the record_component_association_list of a record_aggregate,
if the aggregate's type has a variant_part, then that variant_part
is needed; for the association list of an extension_aggregate,
variant_parts that are part of the aggregate's type, and that are
not part of a record type that is an ancestor of the ancestor
expression's type or of the ancestor subtype, are needed. In
either case, though, a variant_part that is part of the
component_list of an enclosing variant_part is needed only if the
enclosing variant_part is needed, and if the discrete_choice_list
for the component_list containing the inner variant part covers
the value [which must be static] of the discriminant that governs
the enclosing variant_part.
****************************************************************
Questions? Ask the ACAA Technical Agent