Version 1.2 of ai12s/ai12-0399-1.txt

Unformatted version of ai12s/ai12-0399-1.txt version 1.2
Other versions for file ai12s/ai12-0399-1.txt

!standard 9.5(53/5)          20-10-21 AI12-0399-1/02
!standard 10.2.1(4.1/2)
!standard 10.2.1(4.2/2)
!standard 10.2.1(11.1/2)
!standard 10.2.1(11.2/2)
!standard 10.2.1(11.6/2)
!standard 10.2.1(11.7/2)
!standard 10.2.1(11.8/2)
!standard 13.1(11/3)
!standard J.15.14(0)
!class Amendment 20-10-15
!status Amendment 1-2012 20-10-21
!status ARG Approved 13-1-0 20-10-21
!status work item 20-10-15
!status received 20-09-03
!priority Low
!difficulty Easy
!Subject Aspect specification for Preelaborable_Initialization
!summary
We define Preelaborable_Initialization to be an aspect, and allow for the situation where the full view is defined by the language or inheritance to be True, while the partial view is False. We use this for Nonblocking as well, as it has a similar problem, where the full view might be defined by the language to be Nonblocking, even if the partial view defaults to False.
!problem
Preelaborable_Initialization is one of the few remaining pragmas that cannot be specified using an aspect specification. The reason for this is a technicality (see AI05-0229-1):
===pragma Preelaborable_Initialization (referred to as P_I below)
[Editor's Note: This pragma does not work well as a type-related aspect, as it is view dependent. In particular, even if a partial view does not have the P_I property, the full view might have the P_I property. That is contrary to 13.1(11/2) for operational and representation aspects. (In the absence of a change to 13.1(11/2), we'd have a compatibility problem.) ...]
---
This seems like it could be fixed, and it is a bit of an anomaly. I believe the goal was that it was OK if the partial view did not have the aspect visibly True, since you might change the implementation at some point to not have preelaborable initialization. On the other hand, for other aspects we are forcing you to reveal the full view's aspect in the partial view. Nonblocking is currently such an aspect, though we believe this should probably also be changed. There are two conceivable approaches, but only the second really works for Preelaborable_Initialization:
1) Force the partial view to match the full view, and say that it has Preelaborable_Initialization, even if at some later point you fear the implementation might no longer be able to meet that requirement -- alas this doesn't really work as it would require pragma Preelaborable_Initialization for all private types that turn out to have a full type with preelaborable initialization -- this would be quite incompatible with the current language;
2) Allow the partial view and the full view to have different values for certain Boolean-valued aspects, but probably limited to False for the partial view and True for the full view. We already have a rule analogous to this on inheritance of Boolean aspects, in RM 13.1.1(18.1/5):
If an aspect of a derived type (or its first subtype) is inherited from an ancestor (sub)type and has the boolean value True, the inherited value shall not be overridden to have the value False for the derived type (or its first subtype), unless otherwise specified in this International Standard. If an aspect of a nonfirst subtype is inherited from the subtype in the subtype_indication that defines it, and has the value True, the inherited value shall not be overridden to have the value False for the nonfirst subtype, unless otherwise specified in this International Standard.
We do allow aspects to be completely unspecified on a partial view, while being specified on the full view (RM 13.1.1(35/3)). So this could be seen as a variant of that for Boolean aspects for which "False" is the default value if not specified.
!proposal
Modify the general rule about partial view and full view having the same value for all aspects, to allow an exception for certain boolean-valued aspects, where the partial view may be False while the full view is True. We would use this at least for Preelaborable_Initialization where we would allow the full type to be "better behaved" than the partial view. We also apply this to Nonblocking (though it is subtype-specific), for largely the same reason, given that certain subtypes are by definition Nonblocking, and having a requirement to specify Nonblocking => True for the partial view of such a subtype is not upward compatible.
!wording
Modify 3.9(6/5)
type Tag is private[;] [pragma]{with} Preelaborable_Initialization[(Tag)];
Modify 7.6(5/2):
type Controlled is abstract tagged private[;] [pragma]{with} Preelaborable_Initialization[(Controlled)];
Modify 7.6(7/2):
type Limited_Controlled is abstract tagged limited private[;] [pragma]{with} Preelaborable_Initialization[(Limited_Controlled)];
Modify 9.5(53/5) as defined by AI12-0396-1:
It is illegal to directly specify aspect Nonblocking for the first subtype of the full view of a type that has a partial view. If the Nonblocking aspect of the full view is inherited, it shall have the same value as that of the partial view{, or have the value True}.
Move 10.2.1(4.1/2, 4.2/2) defining the pragma Preelaborable_Initialization to Annex J, as section J.15.14.
Modify 10.2.1(11.1/2):
The following rules specify which entities have preelaborable initialization {, namely that the Preelaborable_Initialization aspect of the entity is True}.
Modify 10.2.1(11.2/3):
The partial view of a private type or private extension, a protected type without entry_declarations, a generic formal private type, or a generic formal derived type, has preelaborable initialization if and only if the [pragma] Preelaborable_Initialization {aspect} has been [applied to]{specified True for} them. [Redundant: A protected type with entry_declarations or a task type never has preelaborable initialization.] {The Preelaborable_Initialization aspect of a partial view of a type may be specified as False, even if the full view of the type has preelaborable initialization. Similarly, a generic formal type need hot be specified to have preelaborable initialization, even if the actual type in an instance has preelaborable initialization.}
Move 10.2.1(11.6/2) to Annex J, with modifications (see Annex J below).
Modify 10.2.1(11.7/3):
{The Preelaborable_Initialization aspect shall be directly specified only for a composite type declared within the visible part of a package or a generic package.} [If the pragma appears in the first list of basic_declarative_items of a package_specification, then the direct_name shall denote the first subtype of a composite type, and the type shall be declared immediately within the same package as the pragma.] If the [pragma is applied to]{Preelaborable_Initialization aspect is specified True for} a private type or a private extension, the full view of the type shall have preelaborable initialization. If the [pragma is applied to]{aspect is specified True for} a protected type, the protected type shall not have entries, and each component of the protected type shall have preelaborable initialization. For any other composite type, the [type shall have preelaborable initialization]{aspect shall be specified only if it is confirming}. In addition to the places where Legality Rules normally apply (see 12.3), these rules apply also in the private part of an instance of a generic unit.
Modify 10.2.1(11.c/3):
AARM Reason: {AI05-0028-1} The reason why we need [the pragma]{to specify the aspect} for private types, private extensions, and protected types is fairly clear: the properties of the full view determine whether the type has preelaborable initialization or not; in order to preserve privacy we need a way to express on the partial view that the full view is well-behaved. The reason why we need [the pragma]{to specify the aspect} for other composite types is more subtle: a nonnull override for Initialize might occur in the private part, even for a nonprivate type; in order to preserve privacy, we need a way to express on a type declared in a visible part that the private part does not contain any nasty override of Initialize.
Modify 10.2.1(11.8/2):
If the [pragma appears]{aspect is directly specified on a type declared} in a generic_formal_part, then [the direct_name shall denote]{the type shall be} a generic formal private type or a generic formal derived type declared in the same generic_formal_part as the pragma. In a generic_instantiation the corresponding actual type shall have preelaborable initialization.
Modify 10.2.1(11.d/2):
AARM Ramification: Not only do protected types with entry_declarations and task types not have preelaborable initialization, but they cannot have [pragma]{the aspect} Preelaborable_Initialization [applied to]{specified True for} them.
Modify 11.4.1(2/5):
... type Exception_Id is private[;]
[pragma]{with} Preelaborable_Initialization[(Exception_Id)];
...
Modify 11.4.1(3/2):
type Exception_Occurrence is limited private[;] [pragma]{with} Preelaborable_Initialization[(Exception_Occurrence)]; ...
Modify 13.1(11/3) -- as defined in AI12-0396-1:
If a type-related aspect is defined for the partial view of a type, then it has the same definition for the full view of the type{, except for certain Boolean-valued operational aspects where the language specifies that the partial view can have the value False even when the full view has the value True}. ...
{AARM Discussion: This applies to aspect Preelaborable_Initialization. Nonblocking has a similar rule, though it is a subtype-specific aspect.}
Modify 13.11(6/2):
type Root_Storage_Pool is abstract new Ada.Finalization.Limited_Controlled with private[;] [pragma]{with} Preelaborable_Initialization[(Root_Storage_Pool)];
In a corresponding fashion:
Modify 13.11.4(4/5), (5/3) Modify 13.13.1(3/2)
Modify A.4.2(4/2):
type Character_Set is private[;] [pragma]{with} Preelaborable_Initialization[(Character_Set)];
Modify A.4.5(4/2):
type Unbounded_String is private[;] [pragma]{with} Preelaborable_Initialization[(Unbounded_String)];
Modify A.4.7(4/2):
type Wide_Character_Set is private[;] [pragma]{with} Preelaborable_Initialization[(Wide_Character_Set)];
In a corresponding fashion:
Modify A.4.8(4/2), (20/2) Modify A.12.1(5/4) Modify A.18.2(8/5), (9/2), (79.2/5), (79.3/5) Modify A.18.3(6/5), (7/2), (50.2/5), (50.3/5) Modify A.18.5(3/5), (4/2), (37.3/5), (37.4/5) Modify A.18.6(4/5), (5/2), (51.4/5), (51.5/5) Modify A.18.8(3/5), (4/2), (58.2/5), (58.3/5) Modify A.18.9(4/5), (5/2), (74.2/5), (74.3/5) Modify A.18.10(8.5), (9/3), (70.2/5), (70.3/5) Modify A.18.18(6/5) Modify B.3.1(5/2) Modify C.7.1(2/5) Modify G.1.1(4/2)
Add the following section to Annex J:
J.15.14 Pragma Preelaborable_Initialization:
Syntax
The form of a pragma Preelaborable_Initialization is as follows:
pragma Preelaborable_Initialization(direct_name);
Legality Rules
A pragma Preelaborable_Initialization specifies that the Preelaborable_Initialization aspect (see 10.2.1) for a composite type is True. This pragma shall appear in the visible part of a package or generic package.
If the pragma appears in the first list of basic_declarative_items of a package_specification, then the direct_name shall denote the first subtype of a composite type, and the type shall be declared immediately within the same package as the pragma. The composite type shall be one for which the Preelaborable_Initialization aspect can be directly specified as True. In addition to the places where Legality Rules normally apply (see 12.3), these rules apply also in the private part of an instance of a generic unit.
If the pragma appears in a generic_formal_part, then the direct_name shall denote a type declared in the same generic_formal_part as the pragma, and be one for which the Preelaborable_Initialization aspect can be directly specified as True.
!discussion
It is an anomaly that Preelaborable_Initialization is the only "characteristic" of a type that is not considered an aspect. The reason we had deferred making this an aspect had to do with the now-altered rule that all views of a type would have the same value for all aspects. We now limit that rule to representation aspects. For operational aspects, we recognize that there are reasons why the partial view might want to be different, especially if the full view has a language-defined value for the aspect, which is true for both Preelaborable_Initializaation for certain simple types and for Nonblocking for base subtypes of elementary types. It is awkward for the partial view to be required to reveal this property of the full type, and it would be incompatible to do so for Preelaborable_Initialization, and for Nonblocking, as suddenly various private types would be required to have these aspects explicitly specified.
Therefore, we recognize these special cases, where the default value of False generally imposes no special requirement, while the value of True does impose requirements on the type and some of its operations. For such cases we permit the value for the full type to be True, even if the partial view makes no such "promise" by having the value False for the aspect.
We move the pragma to the Obsolescent Annex (Annex J), to be consistent with our handling of other similar pragmas.
!ASIS
[Not sure. It seems like some new capabilities might be needed, but I didn't check - Editor.]
!ACATS test
ACATS B- and C-Tests are needed to check that the new capabilities are supported.
!appendix

From: John Barnes
Sent: Thursday, September 3, 2020  2:39 PM

I have started to update my book (Programming in Ada 2012) for Ada 202x. As 
a first pass I am correcting all (known) errors and updating it to reflect 
the 2015/2016 revision which is the current standard. Many of those changes 
are in the book anyway. I am also trying to avoid changing the pagination so 
that I don't have to make many changes to the index.

One purpose of this version will be so that the publishers can use it for 
future print runs in the interim. (And as a safeguard against my never getting 
around to doing the full update for any reason such as personal termination.)

At the same time I thought I might as well convert as many pragmas to aspects 
as possible even if they were not done by the 15/16 revision.

But I was very surprised to find that there is no aspect form for the pragma 
Preelaborable_Initialization. I understand that there were a number of awkward 
cases where it was not possible. But all the cases that I have looked at and 
in particular important packages such as Ada,Tags, Ada.Exceptions, 
Ada.Finalization, Ada.Task_Identification, System.Storage_Pools and so on 
could easily use an aspect.

In those examples it is simply a case of replacing

type Something is sortof private;
pragma Preelaborable_Initialization(Something);

by

type Something is sortof private
   with Preelaborable_Initialization;

where sortof could be limited or abstract tagged or abstract tagged limited 
etc (or indeed nothing).

I am assuming that when the final version is produced, we will use aspects in 
a uniform way throughout. At the moment some packages still have pragma 
Preelaborate whereas some use an aspect including for example Nonblocking 
which was convenient when Nonblocking was introduced.

I have been through the whole of the 2012 RM and in every case where 
Preelaborable_Initialization is used, I could see no reason why an aspect 
could not be used. I did it by hand so maybe I missed something.

What is the problem?

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

From: Tucker Taft
Sent: Thursday, September 3, 2020  3:22 PM

There was a technical reason we never made this an aspect (see 
http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai05s/ai05-0229-1.txt?rev=1.28): 

===pragma Preelaborable_Initialization (referred to as P_I below)

[Editor's Note: This pragma does not work well as a type-related aspect, as 
it is view dependent. In particular, even if a partial view does not have the
P_I property, the full view might have the P_I property. That is contrary to 
13.1(11/2) for operational and representation aspects. (In the absence of a 
change to 13.1(11/2), we'd have a compatibility problem.)

We could try to invent new rules specifically for the P_I aspect to handle 
this, but it is more work than this could possibly be worth (there is no 
requirement for this pragma to be an aspect).

Thus we are retaining the pragma and not defining an aspect.]

---

This seems like it could be fixed, and it is a bit of an anomaly.  I believe 
the goal was that it was OK if the partial view did not have the aspect 
visibly True, since you might change the implementation at some point to not 
have preelaborable initialization.  On the other hand, for other aspects we 
are forcing you to reveal the full view's aspect in the partial view.  
Nonblocking is such an aspect.  So I see two fixes:

  1) Force the partial view to match the full view, and say that it has 
     Preelaborable_Initialization, even if at some later point you fear the 
     implementation might no longer be able to meet that requirement;

  2) Allow the partial view and the full view to have different values for 
     certain Boolean-valued aspects, but probably limited to False for the 
     partial view and True for the full view.  We already have a rule 
     analogous to this on inheritance of Boolean aspects, in RM 13.1.1(18.1/5):

"If an aspect of a derived type (or its first subtype) is inherited from an 
ancestor (sub)type and has the boolean value True, the inherited value shall
not be overridden to have the value False for the derived type (or its first
subtype), unless otherwise specified in this International Standard. If an 
aspect of a nonfirst subtype is inherited from the subtype in the 
subtype_indication that defines it, and has the value True, the inherited 
value shall not be overridden to have the value False for the nonfirst 
subtype, unless otherwise specified in this International Standard."

We do allow aspects to be completely unspecified on a partial view, while 
being specified on the full view (RM 13.1.1(35/3)).  So this could be seen as 
a variant of that for Boolean aspects for which "False" is the default value 
if not specified.

Anyway, we need to decide whether we want to make this into an aspect.  If so, 
we can probably make it work.

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

From: John Barnes
Sent: Monday, September 7, 2020  3:34 AM

Thanks for that.  Reading that old AI will keep me quiet for a bit. I am also 
reading the 2012 Rationale which mentions the problem.

I am somewhat horrified that I obviously knew about this once since I wrote 
the Rat and indeed it refers to that AI.

But it would be excellent to find a neat way to tidy up this somewhat ugly 
remnant of widespread pragmas.

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

From: Tucker Taft
Sent: Monday, September 7, 2020  3:01 PM

Agreed.  All we need is yet another AI to fix the problem! ;-)

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

From: Randy Brukardt
Sent: Wednesday, September 9, 2020  2:51 PM

Well, we still have numbers for 9600 possible AIs, so I don't think we need 
to worry about having more AIs. We *do* need a volunteer to write it, though.

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

From: Tucker Taft
Sent: Wednesday, September 9, 2020  3:09 PM

You can feel free to put it on my homework list.  Not much there at the moment!

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

From: Bob Duff
Sent: Wednesday, September 9, 2020  3:55 PM

OK, so Tucker's homework is to write 9600 AIs.

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

From: Tucker Taft
Sent: Wednesday, September 9, 2020  4:07 PM

It sometimes feels that way...

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

From: Randy Brukardt
Sent: Wednesday, September 9, 2020  4:09 PM

> OK, so Tucker's homework is to write 9600 AIs.

LOL! He's well on his way... :-)

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

From: Randy Brukardt
Sent: Thursday, October 15, 2020
[Summary of some private mail on this proposal.]

>> I don't think you have the Nonblocking rule (9.3(53/5)) correct, as it is 
>> written it prevents specifying the aspect to True on the full definition 
>> of a usual private type. According to your logic, that should be OK. It 
>> seems weird to only allow that by inheritance or rule (elementary base 
>> types). 

Tucker:

> I don't think we want you to be able to *directly* specify the same aspect 
> with different values on the partial view and the full view.  We do want you
> to be able to specify one thing on the partial view, and then have the full
> view inherit something else. 

Randy:
 
That's not the case I was thinking about. The rule you have prevents specifying 
the value for the full type even if the partial view leaves it unspecified. That
means that you cannot confirm an inherited value (unless you want to put it on 
the partial view and advertize it to the world), and similarly you can't use 
Nonblocking only in the body for most types.

We have a language design principle that one can always write a confirming 
aspect specification, and this rule seems to violate that.

I realize that Nonblocking is never truly "unspecified", but it is isn't 
mentioned and is inherited from the surrounding unit, which also might not 
explicitly specify the value, the difference is more academic than real.

Tucker:

>> ... That is the point.  We are hiding the fact that the full view is 
>> Nonblocking, so we can change our minds without disturbing the rest of 
>> the world.  Furthermore, the full view is going to be Nonblocking whether 
>> we want it to be or not if the full type is a scalar base subtype.
>> ...
>> [The existing rule] forced you to reveal whether the full type was 
>> Nonblocking, which you might not want to do to allow for later changes 
>> to the full type.

Randy:

> ... it is insane that you can do this *implicitly*, but you are not allowed 
> to do this *explicitly*. What the heck is the difference???
 
> So, I think you have to go all the way if you are making this change. Note 
> that you could always have a null subtype that has explicit Nonblocking on 
> it, so preventing it directly on the full type just is requiring name 
> pollution for no gain whatsoever.
> 
>That is, you are allowing the following:
>
>package P is
>   type Priv is private;
>private
>   type Priv is record ...
>   subtype Sub_Priv is Priv with Nonblocking => True;
>end P;
> 
>but not allowing:
> 
>package P is
>   type Priv is private;
>private
>   type Priv is record ... with Nonblocking => True;
>end P;

Tucker:

I can see your point here.  My main concern was not having different aspect 
values explicitly specified for the partial view and full view of the "same" 
subtype, because I think that will add complexity to implementations without 
sufficient benefit.

Randy:

I guess I can see splitting the baby here. I don't really buy the "complexity 
to implementations" argument, although given that we've removed the ability to
retrieve the value of Nonblocking, someone might come up with something clever
to avoid some work. For me [in Janus/Ada], I will just have to duplicate 
subtypes as needed to get the right effect, and that will get zero benefit 
from an additional restriction. But as I said before, it's very hard to say 
anything very definitive about other implementations.

So, we probably should reword 9.5(53/5) to something like (changes not shown):

  It is illegal to directly specify aspect Nonblocking for the first
  subtype of the full view of a type that has a partial view with aspect
  Nonblocking specified. It is illegal to directly specify aspect 
  Nonblocking to be False for the first subtype of the full view of a 
  type that has a partial view that is nonblocking. If the
  Nonblocking aspect of the full view is inherited, it shall have the
  same value as that of the partial view, or have the value True.

Alternatively, we could add the second sentence of the above to 9.5(54/5), in 
the same form:

  Aspect Nonblocking shall be directly specified for the first subtype of the
  full view of a type that has a partial view only if it has the same value 
  as the Nonblocking aspect of the partial view or if it is specified True. 

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


Questions? Ask the ACAA Technical Agent