Version 1.1 of ai05s/ai05-0220-1.txt

Unformatted version of ai05s/ai05-0220-1.txt version 1.1
Other versions for file 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