4.3.2 Extension Aggregates
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.
Name Resolution Rules
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.
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 Rules than a Name Resolution Rules.
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.
a call to a function with
an unconstrained result subtype; nor
a parenthesized or qualified
expression whose operand would violate this rule; nor
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.
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.
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.
9 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
Examples of extension
aggregates (for types defined in 3.9.1):
Painted_Point'(Point with Red)
(Point'(P) with Paint => Black)
(Expression with Left => 1.2, Right => 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
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
Incompatibilities With Ada 2005
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.
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.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe