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.
Syntax
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.
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
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.
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.
Static Semantics
Dynamic Semantics
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 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
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
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.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe