Ada Conformity Assessment Authority      Home Conformity Assessment   Test Suite ARGAda Standard
Annotated Ada Reference Manual (Ada 2022)Legal Information
Contents   Index   References   Search   Previous   Next 

4.3.1 Record Aggregates

[In a record_aggregate, a value is specified for each component of the record or record extension value, using either a named or a positional association.] 


record_aggregate ::= (record_component_association_list)
record_component_association_list ::= 
    record_component_association {, record_component_association}
  | null record
{AI95-00287-01} record_component_association ::= 
    [component_choice_list =>] expression
   | component_choice_list => <>
{AI12-0212-1} component_choice_list ::= 
     component_selector_name {'|' | component_selector_name}
   | others
A record_component_association is a named component association if it has a component_choice_list; otherwise, it is a positional component association. Any positional component associations shall precede any named component associations. If there is a named association with a component_choice_list of others, it shall come last. 
Discussion: These rules were implied by the BNF in an early version of the RM9X, but it made the grammar harder to read, and was inconsistent with how we handle discriminant constraints. Note that for array aggregates we still express some of the rules in the grammar, but array aggregates are significantly different because an array aggregate is either all positional (with a possible others at the end), or all named. 
In the record_component_association_list for a record_aggregate, if there is only one association, it shall be a named association. 
Reason: {AI05-0264-1} Otherwise, the construct would be interpreted as a parenthesized expression. This is considered a syntax rule, since it is relevant to overload resolution. We choose not to express it with BNF so we can share the definition of record_component_association_list in both record_aggregate and extension_aggregate.
Ramification: The record_component_association_list of an extension_aggregate does not have such a restriction. 

Name Resolution Rules

{AI95-00287-01} The expected type for a record_aggregate shall be a single record type or record extension. 
Ramification: This rule is used to resolve whether an aggregate is an array_aggregate or a record_aggregate. The presence of a with is used to resolve between a record_aggregate and an extension_aggregate.
{AI12-0127-1} 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).] Each component_selector_name selector_name in a record_component_association of a record_aggregate or extension_aggregate shall denote a needed component [(including possibly a discriminant)]. Each component_selector_name in a record_component_association of a record_delta_aggregate (see 4.3.4) shall denote a nondiscriminant component of the type of the aggregate.
Ramification: For the association list of a record_aggregate, “needed components” includes every component of the composite value, but does not include those in unchosen variants (see AI83-309). If there are variants, then the value specified for the discriminant that governs them determines which variant is chosen, and hence which components are needed.
If an extension defines a new known_discriminant_part, then all of its discriminants are needed in the component association list of an extension aggregate for that type, even if the discriminants have the same names and types as discriminants of the type of the ancestor expression. This is necessary to ensure that the positions in the record_component_association_list are well defined, and that discriminants that govern variant_parts can be given by static expressions. 
Reason: We don't define “needed” for record_delta_aggregates so that there is no completeness requirement. But that means that we need to ensure that the rules using “needed” doesn't appear to apply to record_delta_aggregates, and we also need Legality Rules to prevent giving the same component twice and giving components from two different variants. 
Term entry: needed component — component of a record type or record extension that is required to have its value specified within a given aggregate
The expected type for the expression of a record_component_association is the type of the associated component(s); the associated component(s) are as follows: 
For a positional association, the component [(including possibly a discriminant)] in the corresponding relative position (in the declarative region of the type), counting only the needed components;
Ramification: This means that for an association list of an extension_aggregate, only noninherited components are counted to determine the position.
{AI05-0005-1} For a derived type (including type extensions), the order of declaration is defined in 3.4, “Derived Types and Classes”. In particular, all discriminants come first, regardless of whether they are defined for the parent type or are newly added to the derived type. 
For a named association with one or more component_selector_names, the named component(s);
For a named association with the reserved word others, all needed components that are not associated with some previous association. 

Legality Rules

If the type of a record_aggregate is a record extension, then it shall be a descendant of a record type, through one or more record extensions (and no private extensions).
{AI05-0016-1} {AI12-0127-1} A record_component_association_list shall be The reserved words null record only if the list occurs in a record_aggregate or extension_aggregate, and only if there are no components needed for that list in a given record_component_association_list.
Ramification: For example, "(null record)" is a record_aggregate for a null record type. Similarly, "(T'(A) with null record)" is an extension_aggregate for a type defined as a null record extension of T.
{AI05-0016-1} If no components are needed and null record is not used, the record_component_association must necessarily be others => <>, as that is the only record_component_association that does not require an associated component. 
{AI95-00287-01} {AI05-0199-1} {AI12-0046-1} {AI12-0127-1} For a record_aggregate or extension_aggregate, each Each record_component_association other than an others choice with a <> shall have at least one associated component, and each needed component shall be associated with exactly one record_component_association. For a record_delta_aggregate, each component_selector_name of each component_choice_list shall denote a distinct nondiscriminant component of the type of the aggregate. If a record_component_association with an expression has two or more associated components, all of them shall be of the same type, or all of them shall be of anonymous access types whose subtypes statically match. In addition, Legality Rules are enforced separately for each associated component.
Ramification: {AI95-00287-01} These rules apply to an association with an others choice with an expression. An others choice with a <> can match zero components or several components with different types. 
Reason: {AI95-00287-01} Without these rules, there would be no way to know what was the expected type for the expression of the association. Note that some of the rules do not apply to <> associations, as we do not need to resolve anything. We allow others => <> to match no components as this is similar to array aggregates. That means that (others => <>) always represents a default-initialized record or array value. 
This paragraph was deleted.Discussion: {AI12-0046-1} AI83-00244 also requires that the expression shall be legal for each associated component. This is because even though two components have the same type, they might have different subtypes. Therefore, the legality of the expression, particularly if it is an array aggregate, might differ depending on the associated component's subtype. However, we have relaxed the rules on array aggregates slightly for Ada 95, so the staticness of an applicable index constraint has no effect on the legality of the array aggregate to which it applies. See 4.3.3. This was the only case (that we know of) where a subtype provided by context affected the legality of an expression.
Ramification: The rule that requires at least one associated component for each record_component_association implies that there can be no extra associations for components that don't exist in the composite value, or that are already determined by the ancestor expression or subtype of an extension_aggregate.
The second part of the first sentence ensures that no needed components are left out, nor specified twice. 
  {AI12-0046-1} {AI12-0127-1} If a record_component_association with an expression has two or more associated components, all of them shall be of the same type, or all of them shall be of anonymous access types whose subtypes statically match. In addition, Legality Rules are enforced separately for each associated component.
Discussion: {AI12-0046-1} AI83-00244 also requires that the expression shall be legal for each associated component. Ada 95 omitted this wording, as it was thought that all cases of difference had been eliminated. That probably was true, but Ada 2005 reintroduced cases where the types match but the legality differs. For example:
type Rec (D : access Integer) is record
          F : access Integer;
end record;
X : aliased Integer;
      R : Rec := (D | F => X'Access); -- Legal for D, illegal for F
There are additional ways for this to happen; because of cases like the above we require that the Legality Rules are checked individually for each associated component.
{AI05-0220-1} {AI12-0086-1} {AI12-0127-1} For a record_aggregate or extension_aggregate, if a variant_part P is nested within a variant V that is not selected by the discriminant value governing the variant_part enclosing V, then there is no restriction on the discriminant governing P. Otherwise, the value of the The value of a discriminant that governs a variant_part P shall be given by a static expression, or by a nonstatic expression having a constrained static nominal subtype. In this latter case of a nonstatic expression, there shall be exactly one discrete_choice_list of P that covers each value that belongs to the nominal subtype and satisfies the predicates of the subtype, and there shall be at least one such value. unless P is nested within a variant V that is not selected by the discriminant value governing the variant_part enclosing V. 
Ramification: This expression might either be given within the aggregate itself, or in a constraint on the parent subtype in a derived_type_definition for some ancestor of the type of the aggregate.
{AI12-0086-1} This means that in the nonstatic value case, the (static) subtype cannot have a null range. 
  {AI95-00287-01} A record_component_association for a discriminant without a default_expression shall have an expression rather than <>. 
Reason: A discriminant must always have a defined value, but <> means uninitialized for a discrete type unless the component has a default value. 
  {AI12-0127-1} A record_component_association of the record_component_association_list of a record_delta_aggregate shall not:
{AI12-0418-1} use the box compound delimiter <> rather than an expression;
have an expression of a limited type;
omit the component_choice_list; or
Ramification: {AI12-0127-1} A record_delta_aggregate cannot use positional notation; all choices shall be named choices.
have a component_choice_list that is an others choice. 
  {AI12-0127-1} For a record_delta_aggregate, no two component_selector_names shall denote components declared within different variants of the same variant_part.

Dynamic Semantics

The evaluation of a record_aggregate consists of the evaluation of the record_component_association_list.
{AI12-0086-1} {AI12-0451-1} For the evaluation of a record_component_association_list, any per-object constraints (see 3.8) for components specified in the association list are elaborated and any expressions are evaluated and converted to the subtype of the associated component. Any constraint elaborations and expression evaluations (and conversions) occur in an arbitrary order, except that the expression for a discriminant is evaluated (and converted) prior to the elaboration of any per-object constraint that depends on it, which in turn occurs prior to the evaluation and conversion of the expression for the component with the per-object constraint. If the value of a discriminant that governs a selected variant_part is given by a nonstatic expression, and the evaluation of that expression yields a value that does not belong to the nominal subtype of the expression, then Constraint_Error is raised.
Ramification: The conversion in the first rule might raise Constraint_Error. 
Discussion: This check in the first rule presumably happened as part of the dependent compatibility check in Ada 83. 
Ramification: {AI12-0086-1} The test on the value of the discriminant can only fail if the value is outside the base range of its type, does not satisfy the (static) predicates of the subtype (possible when the predicate is disabled), or is an invalid representation. This is a rule similar to that used for case statements. As with case statements, this is not a “check”; it cannot be Suppressed. 
  {AI95-00287-01} For a record_component_association with an expression, the expression defines the value for the associated component(s). For a record_component_association with <>, if the component_declaration has a default_expression, that default_expression defines the value for the associated component(s); otherwise, the associated component(s) are initialized by default as for a stand-alone object of the component subtype (see 3.3.1).
The expression of a record_component_association is evaluated (and converted) once for each associated component.
Ramification: {AI05-0005-1} We don't need similar language for <>, as we're considering the value of <> for each individual component. Each component has its own default expression or its own default initialization (they can be different for each component; the components even could have different types), and each one has to be evaluated. So there is no need to repeat that. 
NOTE   {AI12-0447-1} By the rules given above, for For a record_aggregate with positional associations, expressions specifying discriminant values appear first and in the same order as their corresponding discriminant_specifications, since the known_discriminant_part occurs is given first in the declaration of the type; they have to be in the same order as in the known_discriminant_part.


Example of a record aggregate with positional associations: 
(4, July, 1776)                                     -- see 3.8 
Examples of record aggregates with named associations: 
(Day => 4, Month => July, Year => 1776)
(Month => July, Day => 4, Year => 1776)
(Disk, Closed, Track => 5, Cylinder => 12)          -- see 3.8.1
(Unit => Disk, Status => Closed, Cylinder => 9, Track => 1)
{AI95-00287-01} Examples of component associations with several choices: 
(Value => 0, Succ|Pred => new Cell'(0, nullnull)) -- see 3.10.1
   -- The allocator is evaluated twice:
   -- Succ and Pred designate different cells
(Value => 0, Succ|Pred => <>)                       -- see 3.10.1
   -- Succ and Pred will be set to null
Examples of record aggregates for tagged types (see 3.9 and 3.9.1):
Expression'(null record)
Literal'(Value => 0.0)
Painted_Point'(0.0, Pi/2.0, Paint => Red)

Extensions to Ada 83

Null record aggregates may now be specified, via "(null record)". However, this syntax is more useful for null record extensions in extension aggregates.

Wording Changes from Ada 83

Various AIs have been incorporated (AI83-00189, AI83-00244, and AI83-00309). In particular, Ada 83 did not explicitly disallow extra values in a record aggregate. Now we do. 

Extensions to Ada 95

{AI95-00287-01} <> can be used in place of an expression in a record_aggregate, default initializing the component. 

Wording Changes from Ada 95

{AI95-00287-01} Limited record_aggregates are allowed (since all kinds of aggregates can now be limited, see 4.3).

Incompatibilities With Ada 2005

{AI05-0220-1} Correction: Corrected wording so that the rule for discriminants governing variant_parts was not effectively circular. The change makes a few aggregates where a nonstatic discriminant governs an empty variant_part illegal. However, most Ada implementations already enforce some version of the new rule and already reject these aggregates. So it is unlikely that any incompatibility will be noticed in practice.

Extensions to Ada 2005

{AI05-0016-1} Correction: Fixed the wording so that others => <> can be used in place of null record. This is needed to avoid a generic contract issue for generic bodies: we do not want to have to assume the worst to disallow others => <> if the record type might be a null record.
{AI05-0199-1} Correction: We now allow multiple components with anonymous access types to be specified with a single component association. This is to be consistent with the capabilities of a named access type. 

Extensions to Ada 2012

{AI12-0086-1} The value of a discriminant that governs a variant_part in an aggregate can be nonstatic if the nominal subtype of the discriminant expression is static and all possible values select a single variant.

Wording Changes from Ada 2012

{AI12-0046-1} Corrigendum: We explicitly say that the Legality Rules have to be rechecked for each component individually. This seems obvious, but as the AARM note 4.3.1 (16.c) appeared to say that this was not necessary, and since we explicitly state this sort of thing for generic instances, it seemed better to be explicit.
{AI12-0127-1} Made wording changes for delta_aggregates.

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