Ada Conformity Assessment Authority      Home Conformity Assessment   Test Suite ARGAda Standard
Annotated Ada Reference ManualLegal Information
Contents   Index   References   Search   Previous   Next 

3.8.1 Variant Parts and Discrete Choices

A record type with a variant_part specifies alternative lists of components. Each variant defines the components for the value or values of the discriminant covered by its discrete_choice_list.
Discussion: Discrete_choice_lists and discrete_choices are said to cover values as defined below; which discrete_choice_list covers a value determines which of various alternatives is chosen. These are used in variant_parts, array_aggregates, and case_statements.

Language Design Principles

The definition of “cover” in this subclause and the rules about discrete choices are designed so that they are also appropriate for array aggregates and case statements.
The rules of this subclause intentionally parallel those for case statements. 


variant_part ::= 
   case discriminant_direct_name is
   end case;
variant ::= 
   when discrete_choice_list =>
discrete_choice_list ::= discrete_choice {| discrete_choice}
{AI05-0153-3} {AI05-0158-1} discrete_choice ::= choice_expression | discrete_subtype_indication | range | others

Name Resolution Rules

The discriminant_direct_name shall resolve to denote a discriminant (called the discriminant of the variant_part) specified in the known_discriminant_part of the full_type_declaration that contains the variant_part. The expected type for each discrete_choice in a variant is the type of the discriminant of the variant_part.
Ramification: A full_type_declaration with a variant_part has to have a (new) known_discriminant_part; the discriminant of the variant_part cannot be an inherited discriminant. 

Legality Rules

The discriminant of the variant_part shall be of a discrete type. 
Ramification: It shall not be of an access type, named or anonymous.
{AI05-0153-3} The choice_expressions, subtype_indications, and ranges given as discrete_choices in a variant_part shall be static. The discrete_choice others shall appear alone in a discrete_choice_list, and such a discrete_choice_list, if it appears, shall be the last one in the enclosing construct.
A discrete_choice is defined to cover a value in the following cases: 
{AI05-0262-1} A discrete_choice that is a choice_expression covers a value if the value equals the value of the choice_expression converted to the expected type.
{AI05-0153-3} {AI05-0262-1} {AI12-0071-1} A discrete_choice that is a subtype_indication covers all values (possibly none) that belong to the subtype and that satisfy the static predicates predicate of the subtype (see 3.2.4).
Ramification: {AI05-0262-1} A dynamic predicate is never allowed in this case (for variants, case_statements, and case_expressions, a subtype with a dynamic predicate isn't static and thus isn't allowed in a discrete_choice, and for a choice in an array_aggregate, a dynamic predicate is explicitly disallowed — see 3.2.4).
{AI05-0153-3} A discrete_choice that is a range covers all values (possibly none) that belong to the range.
The discrete_choice others covers all values of its expected type that are not covered by previous discrete_choice_lists of the same construct. 
Ramification: For case_statements, this includes values outside the range of the static subtype (if any) to be covered by the choices. It even includes values outside the base range of the case expression's type, since values of numeric types (and undefined values of any scalar type?) can be outside their base range.
A discrete_choice_list covers a value if one of its discrete_choices covers the value.
The possible values of the discriminant of a variant_part shall be covered as follows: 
{AI05-0153-3} {AI05-0188-1} {AI05-0262-1} {AI12-0071-1} If the discriminant is of a static constrained scalar subtype then, except within an instance of a generic unit, each non-others discrete_choice shall cover only values in that subtype that satisfy its predicates predicate, and each value of that subtype that satisfies its predicates predicate shall be covered by some discrete_choice [(either explicitly or by others)];
Reason: {AI05-0188-1} The exemption for a discriminated type declared in an instance allows the following example: 
   type T is new Integer;
package G is
   type Rec (Discrim : T) is record
      case Discrim is
         when -10 .. -1 =>
            Foo : Float;
         when others =>
      end case;
   end record;
end G;
package I is new G (Natural); -- Legal
{AI05-0264-1} If the type of the discriminant is a descendant of a generic formal scalar type, then the variant_part shall have an others discrete_choice;
Reason: The base range is not known statically in this case. 
Otherwise, each value of the base range of the type of the discriminant shall be covered [(either explicitly or by others)].
Two distinct discrete_choices of a variant_part shall not cover the same value.

Static Semantics

If the component_list of a variant is specified by null, the variant has no components.
The discriminant of a variant_part is said to govern the variant_part and its variants. In addition, the discriminant of a derived type governs a variant_part and its variants if it corresponds (see 3.7) to the discriminant of the variant_part.

Dynamic Semantics

A record value contains the values of the components of a particular variant only if the value of the discriminant governing the variant is covered by the discrete_choice_list of the variant. This rule applies in turn to any further variant that is, itself, included in the component_list of the given variant.
   {AI05-0290-1} When an object of a discriminated type T is initialized by default, Constraint_Error is raised if no discrete_choice_list of any variant of a variant_part of T covers the value of the discriminant that governs the variant_part. When a variant_part appears in the component_list of another variant V, this test is only applied if the value of the discriminant governing V is covered by the discrete_choice_list of V
Implementation Note: This is not a “check”; it cannot be suppressed. However, in most cases it is not necessary to generate any code to raise this exception. A test is needed (and can fail) in the case where the discriminant subtype has a Static_Predicate specified, it also has predicate checking disabled, and the discriminant governs a variant_part which lacks a when others choice.
The test also could fail for a static discriminant subtype with range checking suppressed and the discriminant governs a variant_part which lacks a when others choice. But execution is erroneous if a range check that would have failed is suppressed (see 11.5), so an implementation does not have to generate code to check this case. (An unchecked failed predicate does not cause erroneous execution, so the test is required in that case.)
Like the checks associated with a per-object constraint, this test is not made during the elaboration of a subtype_indication.
The elaboration of a variant_part consists of the elaboration of the component_list of each variant in the order in which they appear. 


Example of record type with a variant part: 
type Device is (Printer, Disk, Drum);
type State  is (Open, Closed);
type Peripheral(Unit : Device := Disk) is
      Status : State;
      case Unit is
         when Printer =>
            Line_Count : Integer range 1 .. Page_Size;
         when others =>
            Cylinder   : Cylinder_Index;
            Track      : Track_Number;
         end case;
      end record;
Examples of record subtypes: 
subtype Drum_Unit is Peripheral(Drum);
subtype Disk_Unit is Peripheral(Disk);
Examples of constrained record variables: 
Writer   : Peripheral(Unit  => Printer);
Archive  : Disk_Unit;

Extensions to Ada 83

In Ada 83, the discriminant of a variant_part is not allowed to be of a generic formal type. This restriction is removed in Ada 95; an others discrete_choice is required in this case. 

Wording Changes from Ada 83

The syntactic category choice is removed. The syntax rules for variant, array_aggregate, and case_statement now use discrete_choice_list or discrete_choice instead. The syntax rule for record_aggregate now defines its own syntax for named associations.
{AI05-0299-1} We have added the term Discrete Choice to the title since this is where they are talked about. This is analogous to the name of the subclause "Index Constraints and Discrete Ranges" in the subclause on Array Types.
The rule requiring that the discriminant denote a discriminant of the type being defined seems to have been left implicit in RM83. 

Incompatibilities With Ada 2005

{AI05-0158-1} Membership tests are no longer allowed as a discrete_choice, in order that those tests can be expanded to allow multiple tests in a single expression without ambiguity. Since a membership test has a boolean type, they are very unlikely to be used as a discrete_choice.

Extensions to Ada 2005

{AI05-0153-3} Subtypes with static predicates can be used in discrete_choices, and the coverage rules are modified to respect the predicates.
{AI05-0188-1} Variants in generic specifications are no longer rejected if the subtype of the actual type does not include all of the case choices. This probably isn't useful, but it is consistent with the treatment of case_expressions.

Wording Changes from Ada 2005

{AI05-0290-1} Added a test that some variant covers the value of a discriminant that governs a variant_part. This is similar to the test that some case limb covers the value of the Selecting_expression of a case_statement. This test cannot change the behavior of any nonerroneous Ada 2005 program, so it is not an inconsistency. 

Wording Changes from Ada 2012

{AI12-0071-1} Corrigendum: Updated wording of the coverage rules to use the new term "satisfies the predicates" (see 3.2.4).

Contents   Index   References   Search   Previous   Next 
Ada-Europe Ada 2005 and 2012 Editions sponsored in part by Ada-Europe