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.2 Extension Aggregates

[An extension_aggregate specifies a value for a type that is a record extension by specifying a value or subtype for an ancestor of the type, followed by associations for any components not determined by the ancestor_part.]

Language Design Principles

The model underlying this syntax is that a record extension can also be viewed as a regular record type with an ancestor "prefix". The record_component_association_list corresponds to exactly what would be needed if there were no ancestor/prefix type. The ancestor_part determines the value of the ancestor/prefix. 


extension_aggregate ::= 
    (ancestor_part with record_component_association_list)
ancestor_part ::= expression | subtype_mark

Name Resolution Rules

{AI95-00287-01} The expected type for an extension_aggregate shall be a single type that is a record extension. If the ancestor_part is an expression, it is expected to be of any tagged type. 
Reason: We could have made the expected type T'Class where T is the ultimate ancestor of the type of the aggregate, or we could have made it even more specific than that. However, if the overload resolution rules get too complicated, the implementation gets more difficult and it becomes harder to produce good error messages.
Ramification: {AI05-0005-1} This rule is additive with the rule given in 4.3. That means the 4.3 rule must be satisfied even though it is always syntactically possible to tell that something is an extension aggregate rather than another kind of aggregate. Specifically, that means that an extension aggregate is ambiguous if the context is overloaded on array and/or untagged record types, even though those are never legal contexts for an extension aggregate. Thus, this rule acts more like a Legality Rule than a Name Resolution Rule. 

Legality Rules

{AI95-00306-01} {AI05-0115-1} If the ancestor_part is a subtype_mark, it shall denote a specific tagged subtype. If the ancestor_part is an expression, it shall not be dynamically tagged. The type of the extension_aggregate shall be a descendant of the type of the ancestor_part (the ancestor type), through one or more record extensions (and no private extensions). If the ancestor_part is a subtype_mark, the view of the ancestor type from which the type is descended (see 7.3.1) shall not have unknown discriminants. 
Reason: {AI95-00306-01} The expression cannot be dynamically tagged to prevent implicit "truncation" of a dynamically-tagged value to the specific ancestor type. This is similar to the rules in 3.9.2
 {AI05-0067-1} {AI05-0244-1} {AI12-0236-1} {AI12-0317-1} If the type of the ancestor_part is limited and at least one component is needed in the record_component_association_list, then the ancestor_part shall not have an operative constituent expression (see 4.4) that is a call to a function with an unconstrained result subtype. be:
{AI12-0317-1} a call to a function with an unconstrained result subtype; nor
{AI12-0317-1} a parenthesized or qualified expression whose operand would violate this rule; nor
{AI12-0317-1} a conditional_expression (see 4.5.7) having at least one dependent_expression that would violate this rule. 
Reason: {AI05-0067-1} {AI05-0244-1} This restriction simplifies implementation, because it ensures that either the caller or the callee knows the size to allocate for the aggregate. Without this restriction, information from both caller and callee would have to be combined to determine the appropriate size.
{AI05-0067-1} The (F(...) with null record) case is exempt from this rule, because such extension aggregates are created internally for inherited functions returning null-extension types — we can't very well make those illegal. Moreover, we don't need the rule for null extensions, as the result can simply use the space returned by the function call.
{AI12-0317-1} The mention of “operative constituents” means that constructs like parenthesized expressions, qualified_expressions, and conditional_expressions are ignored when enforcing this rule. 

Static Semantics

For the record_component_association_list of an extension_aggregate, the only components needed are those of the composite value defined by the aggregate that are not inherited from the type of the ancestor_part, plus any inherited discriminants if the ancestor_part is a subtype_mark that denotes an unconstrained subtype. 

Dynamic Semantics

For the evaluation of an extension_aggregate, the record_component_association_list is evaluated. If the ancestor_part is an expression, it is also evaluated; if the ancestor_part is a subtype_mark, the components of the value of the aggregate not given by the record_component_association_list are initialized by default as for an object of the ancestor type. Any implicit initializations or evaluations are performed in an arbitrary order, except that the expression for a discriminant is evaluated prior to any other evaluation or initialization that depends on it.
{AI05-0282-1} If the type of the ancestor_part has discriminants and the ancestor_part is not a subtype_mark that denotes an unconstrained subtype, then a check is made that each discriminant determined by the ancestor_part has the value specified for a corresponding discriminant, if any, either in the record_component_association_list, or in the derived_type_definition for some ancestor of the type of the extension_aggregate. Constraint_Error is raised if this check fails. 
Ramification: Corresponding and specified discriminants are defined in 3.7. The rules requiring static compatibility between new discriminants of a derived type and the parent discriminant(s) they constrain ensure that at most one check is required per discriminant of the ancestor expression.
{AI05-0282-1} The check needs to be made any time that the ancestor is constrained; the source of the discriminants or the constraints is irrelevant. 
NOTE 1   {AI12-0447-1} By the rules given in 4.3.1, if If all components of the value of the extension_aggregate are determined by the ancestor_part, then the record_component_association_list will is required to be simply null record.
NOTE 2   If the ancestor_part is a subtype_mark, then its type can be abstract. If its type is controlled, then as the last step of evaluating the aggregate, the Initialize procedure of the ancestor type is called, unless the Initialize procedure is abstract (see 7.6). 


Examples of extension aggregates (for types defined in 3.9.1):
Painted_Point'(Point with Red)
(Point'(P) with Paint => Black)
{AI12-0178-1} (Expression with Left =>  new Literal'(Value => 1.2),
 Right => new Literal'(Value => 3.4))
Addition'(Binop with null record)
             -- presuming Binop is of type Binary_Operation

Extensions to Ada 83

The extension aggregate syntax is new. 

Incompatibilities With Ada 95

{AI95-00306-01} Amendment Correction: Eliminated implicit “truncation” of a dynamically tagged value when it is used as an ancestor expression. If an aggregate includes such an expression, it is illegal in Ada 2005. Such aggregates are thought to be rare; the problem can be fixed with a type conversion to the appropriate specific type if it occurs. 

Wording Changes from Ada 95

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

Inconsistencies With Ada 2005

{AI05-0282-1} Correction: An extension_aggregate with an ancestor_part whose discriminants are constrained and inherited might now raise Constraint_Error if the aggregate's type is constrained, while it was OK in Ada 2005. In almost all cases, this will make no difference as the constraint will be checked by the immediately following use of the aggregate, but it is possible to compare such an aggregate for equality; in this case, no exception would be raised by Ada 2005, while Ada 2012 will raise Constraint_Error. This should be very rare, and having the possibility means that the representation of the aggregate type has to be able to support unconstrained values of the type, even if the first subtype is constrained and no such objects can be created any other way. 

Incompatibilities With Ada 2005

{AI05-0067-1} Correction: A limited unconstrained ancestor expression that is a function call is now illegal unless the extension part is null. Such aggregates were first introduced in Ada 2005 and are very complex to implement as they must be built-in-place with an unknown size; as such, it is unlikely that they are implemented correctly in existing compilers and thus not often used in existing code.
{AI05-0115-1} Correction: An ancestor_part that is a subtype with unknown discriminants is now explicitly illegal. Such a subtype should not be used to declare an object, and the ancestor_part acts like an object. The Ada 95 rules did not disallow such cases, so it is possible that code exists that uses such an ancestor, but this should be rare. 

Wording Changes from Ada 2012

{AI12-0317-1} Rewrote a Legality Rule to use the new term “operative constituent” in order to reduce duplication of text about ignoring parenthesized expressions and similar constructs. 

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