Version 1.2 of 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