!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 => ); 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. ****************************************************************