Version 1.2 of ais/ai-00389.txt

Unformatted version of ais/ai-00389.txt version 1.2
Other versions for file ais/ai-00389.txt

!standard 4.3.1(8)          04-11-11 AI95-00389/02
!class amendment 04-11-11
!status work item 04-11-11
!status received 04-11-11
!priority Medium
!difficulty Medium
!subject Allow aggregates of partial views
!summary
An aggregate of a partial view is allowed; such an aggregate must contain "others => <>" to default initialize the components only known to the full view.
!problem
AI95-00287 introduces the <> (box) notation for default initializing components of an aggregate. This can be used on any type. However, aggregates of a partial view (which is considered to be a composite type) are not allowed. Default-initialized aggregates of a partial view should be allowed.
Default-initialized aggregates are especially useful to define constants (which are required to be initialized) outside of the defining package of a private type. They also can be useful to explicitly show that the default initialization of an object is intended and important to proper functioning of a program.
!proposal
Allow record aggregates to be of a partial view. The needed components still are those of the full view, even though the components of the full view cannot be named. An aggregate of a partial view must include "others => <>"; this is needed to avoid any dependence on the components of the full view.
Note that if known discriminants are given for the type, they can be specified along with "others => <>".
!wording
The wording of this AI assumes the wording changes of AI-287 have been applied.
Change 4.3.2(8):
The expected type for a record_aggregate shall be a single record type, record extension, partial view of a type, formal private type, or composite formal derived type.
4.3.2(9) is unchanged. Add additional AARM notes to the end of the paragraph:
Ramification: For a partial view, all of the components of the full type are needed, even though not all of them can be named in the aggregate. For a generic formal type, all of the components of the actual type are needed, even though not all of them can be named in the aggregate.
To Be Honest: For a partial view, if the full view of the type is not composite, it is thought of as a record containing one component of the full type.
Modify the start of 4.3.2(16) to:
Each record_component_association {other than an OTHERS choice with a <>} shall have at least one associated component...
Modify the AARM Note 4.3.2(16.a): These rules apply to an association with an others choice {with an expression}. {An others choice with a <> can match a null record type or a null extension.}
[Author's Note: This is needed so that an others choice for a partial view can match a null record full type. This is required so that we don't "leak" information about the full type to the uses. I believe that this is really a bug in AI-287 anyway; a default-initializing others should be allowed to match nothing, as it is harmless (by using OTHERS you've turned off completeness checking anyway) and useful.]
Add after 4.3.2(17.1): (The new Legality Rule added by AI-287)
If the type of the aggregate is a partial view of a type, a formal private type, or a composite formal derived type:
* The aggregate shall include OTHERS => <>; and
AARM Note: This is needed to avoid "leaking" information about the full type to the aggregate. Without this rule, if the full type was NULL RECORD, NULL RECORD could be used; and if the full type had only one component, OTHERS => some-expression could be used. That would clearly break privacy. Similar issues apply to formal types; if information about the actual type could be used in the aggregate, we'd have a generic contract issue. Since each component can only occur in a single association, this rule prevents those issues.
* The type of the aggregate shall not have unknown discriminants.
AARM Note: Unknown discriminants are often used to prevent uncontrolled initialization of objects, and we don't want to provide an uncontrolled initialization mechanism for such types.
!discussion
This capability is a natural extension to that provided by AI-287. It is especially odd that such initializations are allowed in larger aggregates, just not for a complete object. For instance, given that Priv is a private type:
type Wrapper is record P : Priv; end record;
Obj1 : constant Priv := (others => <>); -- Illegal by AI-287, allowed here. Obj2 : constant Wrapper := (others => <>); -- Legal by AI-287.
We have chosen not to define extension aggregates for partial extensions. These would have implementation issues, and for the most part duplicate functionality of record aggregates for partial views.
Implementing an extension aggregate of a partial view would require a mechanism to default-initialize only the extension part of a type. This would be a new capability; while Ada compilers routinely have to default-initialize entire objects of a type (optionally with specified discriminants), they don't have to do that for a portion of a type (except for constructing the default-initialization of a containing type). This would be especially messy for type derived from a generic formal derived type, as the details of the extension parts would come from the actual type.
Moreover, an extension aggregate of a partial extension using a subtype ancestor is identical in meaning to a record aggregate of the same type. That is (Some_Parent with others => <>) is just a complicated way to say (others => <>), since the Some_Parent part is also default initialized.
We do lose the capability to initialize the parent part with an expression for a partial view, but this ability doesn't seem to be worth the implementation burden.
!example
(See discussion.)
--!corrigendum
!ACATS test
ACATS tests need to be constructed to check that aggregates of partial views are allowed and allow the inclusion of discriminant values.
!appendix

From: Randy Brukardt
Sent: Wednesday, November 10, 2004  1:53 PM

I think it would be important if it worked for private types (which are by far
the most common); it's not very interesting for non-limited records, as the
default initialization is available anyway.

It's unfortunate that (<>) is not *always* a shorthand for default
initialization.

   Cnst : constant Priv := (<>);

comes up periodically; moreover, I would much prefer to be able to explicitly
initialize everything (that's currently not possible for private types that you
want or must use the default initialization for).

****************************************************************

From: Tucker Taft
Sent: Wednesday, November 10, 2004  2:26 PM

I believe we always disallow use of "(<>)" so presumably you
meant "(others => <>)".  Allowing this for private types
would seem to be reasonable, since we consider them to
be "composite" types.  If they have visible discriminants,
then presumably we would allow "(Discrim => X, others => <>)".
I think the danger would be that if the private type turned
out to be a non-composite type in its full definition, the
notation "(others => <>)" would be legal only where you
have a *partial* view, which is somewhat unpleasant.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, November 10, 2004  6:36 PM

Yes, that is a bit unpleasant, although I would claim it is because there
exist types that you can't give aggregates. Doesn't seem like a big deal
though.

A quick look at the Standard suggests that the best place to put the needed
wording would be under record aggregates. The important features are:

The type of an aggregate can be a partial view of a type.

For a record_aggregate for a partial view, all components of the type are
*needed* [(but only known discriminants can be named)].

AARM To Be Honest: If the full view of the type is not composite, it is
thought of as a record containing one component of the full type.

If the type is a partial view, the following additional Legality Rules
exist:

* The partial view shall not have unknown discriminants.
* The aggregate shall include others => <>.

Comments?

****************************************************************

From: Randy Brukardt
Sent: Wednesday, November 10, 2004  6:44 PM

BTW, the justification for allowing aggregates of private types would be that
you're allowed to default initialize them *inside* of a larger aggregate, it
seems silly to not allow it on a complete stand-alone object. That is, given
Priv is a private type:

    type Wrapper is record
       P : Priv;
    end record;

    Obj1 : constant Priv := (others => <>); -- Illegal by AI-287.
    Obj2 : constant Wrapper := (others => <>); -- Legal by AI-287.

****************************************************************

From: Gary Dismukes
Sent: Wednesday, November 10, 2004  7:18 PM

That's a convincing justification for allowing it, and the partial view
issue doesn't seem like a major stumbling block (i.e., it could reasonably
be resolved along the lines you suggested in your other message).

****************************************************************

From: Pascal Leroy
Sent: Thursday, November 11, 2004  1:14 PM

I hate to bring that up, but: what about generic formal private types?  It
you allow aggregates for those (which would seem consistent) the compilers
which do macro-expansion might end up with aggregates of an elementary
type.  That gives me the willies.

****************************************************************

From: Randy Brukardt
Sent: Thursday, November 11, 2004  1:34 PM

I don't see why; such an aggregate means "default-initialize", which usually
means do nothing at all. I'd much prefer that (others => <>) worked for *all*
types, but given that it usually would mean "do nothing" for an elementary type
(something we certainly don't want to encourage by giving a way to write it), I
didn't propose that.

In any case, this proposal means that having aggregates of an elementary type
is a possibly (if the full type is elementary), so I don't think that there is
any additional hardship offered by a generic formal type.

****************************************************************

From: Robert A. Duff
Sent: Thursday, November 11, 2004  3:34 PM

> Here's an AI writeup on the aggregates of partial views idea. We can discuss
> it as a "hole-filling" idea. Comments welcome.

Looks good to me.

> [Author's Note: This is needed so that an others choice for a partial view
> can match a null record full type. This is required so that we don't "leak"
> information about the full type to the uses. I believe that this is really a
> bug in AI-287 anyway; a default-initializing others should be allowed to
> match
> nothing, as it is harmless (by using OTHERS you've turned off completeness
> checking anyway) and useful.]

I understand why it's useful *here*, but why is it useful with just the
AI-287 change?

> If the aggregate denotes a partial view of a type, then the aggregate shall
> include OTHERS => <>.

I don't think you mean "denotes" here.  Aggregates don't denote types.
How about, "If the type of the aggregate is a partial..."

Some of the wording says "without an expression".  Does that mean "with
a box"?  And wouldn't the latter be clearer?

I agree with Pascal that we need to do likewise for generic formal
private types.  But I agree with Randy that that's not a problem.

****************************************************************

From: Randy Brukardt
Sent: Thursday, November 11, 2004  4:57 PM

> > [Author's Note: This is needed so that an others choice for a partial view
> > can match a null record full type. This is required so that we don't "leak"
> > information about the full type to the uses. I believe that this is really a
> > bug in AI-287 anyway; a default-initializing others should be allowed to match
> > nothing, as it is harmless (by using OTHERS you've turned off completeness
> > checking anyway) and useful.]
>
> I understand why it's useful *here*, but why is it useful with just the
> AI-287 change?

Because it lets you have the inverse of the completeness check when that's
appropriate. That is, the aggregate won't need to be changed even in the
face of added or deleted components, so long as the ones that you care about
aren't changed.

It's a minor need, for sure, but I mentioned it to explain why I made the
rule apply always, and not just for aggregates of partial views.

> > If the aggregate denotes a partial view of a type, then the aggregate shall
> > include OTHERS => <>.
>
> I don't think you mean "denotes" here.  Aggregates don't denote types.
> How about, "If the type of the aggregate is a partial..."

Yeah, you're probably right here. Wrote this too fast...

> Some of the wording says "without an expression".  Does that mean "with
> a box"?  And wouldn't the latter be clearer?

I suppose; none of the existing wording ever says anything like "with a <>",
and I was trying to stay within the syntax.

> I agree with Pascal that we need to do likewise for generic formal
> private types.  But I agree with Randy that that's not a problem.

I was presuming that formal types were covered. If not, then we have nasty
wording, because you have to include not only formal private types but also
formal derived types whose ancestor is composite. Adding all of that to all
of the rules bloats things up a lot. That is,
"partial view of a type, a generic formal private type, or a generic formal
derived type whose ancestor is a composite type".

Yuck. I suppose we could try to give a name to that, but its a mixture of
views and types. Or maybe put that into a header and make the legality rules
bullets.

****************************************************************


Questions? Ask the ACAA Technical Agent