Version 1.1 of ai05s/ai05-0035-1.txt

Unformatted version of ai05s/ai05-0035-1.txt version 1.1
Other versions for file ai05s/ai05-0035-1.txt

!standard 10.2.1(15.5/2)          07-01-12 AI05-0035-1/01
!class binding interpretation 07-01-12
!status work item 07-01-12
!status received 07-01-12
!priority Medium
!difficulty Easy
!qualifier Omission
!subject Inconsistences with pure units
!summary
The rules for pure units are enforced inside of generic units (not just inside of instance specifications).
Only subunits that are elaborated are required to be pure, just as in the case of preelaborated units.
!question
1 - The elaboration of generic units (as opposed to instances) does exactly nothing. The rules 10.2.1(15.1/2-15.5/2) therefore do not apply inside of a pure generic unit.
Rechecking will happen on the instance, but because the boilerplate text is not given in 10.2.1(17/2), rechecking only happens in the visible part.
That means that the pure unit restrictions are not applied to the private part and body of a generic unit. That provides a simple way to add a variable to a pure unit: just instantiate an appropriate generic. That doesn't seem right...
Contrast this to the situation for preelaborated units: the rules apply in the private part, and there are special rules to apply to generic bodies. All of this seems to be missing for pure units.
Is this hole intended? (No.)
2 - AI95-0002 changes the rules in 10.2.1(11/1) to exclude some subunits of preelaborated units to not require preelaboration.
However, no corresponding change was made to pure units. The same considerations seem to apply: something legal in a nested unit shouldn't become illegal simply because the unit was changed into a subunit. Moreover, "pure" never seems to have been considered in AI95-0002, so it appear this difference is an oversight.
Moreover, since pure units are also preelaborated, we have the bizarre situation where a unit needs pure restriction checks but not preelaboration restriction checks. This combination seems to provide more confusion than value.
Should this rule be changed to match preelaboration? (Yes.)
!recommendation
(See Summary.)
!wording
1 - Add after 10.2.1(15.5/2):
A generic unit is pure only if elaboration of the corresponding unit of an instance would not perform any such actions.
2 - Change 10.2.1(17/2) to:
A pragma Pure is used to declare that a library unit is pure. {The declaration and body of a declared pure library unit, and all subunits that are elaborated as part of elaborating the library unit, shall be pure. In addition, all} [If a pragma Pure applies to a library unit, then its[ compilation units {of a declared pure library unit} [shall be pure, and they] shall depend semantically only on compilation units of other library units that are declared pure. Furthermore, the full view of any partial view declared in the visible part of the library unit that has any available stream attributes shall support external streaming (see 13.13.2).
!discussion
1 - None of the rules in 10.2.1(15.1-15.5/2) depend on the properties of the actual type. Therefore, there is no advantage to delaying the legality checks, and the complication of rechecking in the instance is avoided. This is slightly different (but much simpler) than the preelaboration rules.
2 - The rules for Preelaborate and Pure are supposed to be parallel to each other, and this is an unnecessary difference.
--!corrigendum A.18.2(239/2)
!ACATS test
1 - B-Tests should be created to ensure that the checks are made in the generic unit.
2 - A C-Test should ensure that a package subunit of a pure subprogram does not need to be pure.
!appendix

From: Randy Brukardt
Date: Friday, January 12, 2007  7:31 PM

Pascal had written:

> The elaboration of generic specifications does exactly nothing.  So
> anything is permitted in a generic specification.  Rechecking will happen
> on the instance, and then only if the instance itself is marked as
> preelaborable.  Where we need special rules is for generic bodies, because
> while the elaboration of generic bodies also does nothing, we won't have a
> chance to recheck anything on the instance.  All of this is nicely
> explained in AARM 10.2.1(10.a.1/2).

Well, while I agree with your explanation, now I have a new worry, having moved
on to Pure.

Following this explanation, none of the extra Pure restrictions of
10.2.1(15.1-15.4/2) would enforced inside of a generic template. Moreover,
10.2.1(17/2) does not have the wording to enforce them in a private part. And
there is no generic special cases for Pure like there are for Preelaborate.
Therefore, I must conclude that they're never enforced for the private part
and body of generic units.

Thus, if you want a variable or allocator or access type with non-empty
collection in a Pure package, just instantiate an appropriate generic. That
doesn't seem right...

Example:

     generic
        type Anything is private;
        pragma Preelaborable_Initialization (Anything);
     package Add_a_Var is
        pragma Pure (Add_A_Var);
        procedure Set (Val : in Anything);
        function Get return Anything;
     end Add_a_Var;

     package body Add_a_Var is
        My_Var : Anything; -- Legal, elab of Add_a_Var does not elaborate this.
                           -- Anything has PInit in order to pass 10.2.1(10.1/2).
        procedure Set (Val : in Anything) is
        begin
            My_Var := Val;
        end Set;
        function Get return Anything is
        begin
            return My_var;
        end Get;
     end Add_a_Var;

     with Add_a_Var;
     package Oops is
         pragma Pure (Oops);
         package Int_Var is new Add_a_Var (Integer); -- Legal, nothing bad in visible part.
     end Oops;

And now you've added a variable to your Pure package, upsetting everything that
assumes no state.

I suspect that we need to do two things to plug this hole:

(1) Add the boilerplate to 10.2.1(17/2) so that the additional Pure rules are
    rechecked in the private part;
(2) Add after 10.2.1(15.6/2) something like:

A generic_body is pure only if elaboration of a corresponding instance body
would not perform any such actions.

[We don't need any "presuming that"s, because 15.2-5/2 don't depend on the
properties of the types involved, other than that it is access type.]

Humm, since the rules don't depend on the formal types, probably we should
simply enforce them in both halves of the generic unit (that is, in both the
spec and body). That doesn't require any rechecking in an instance. Of course,
that would be different than the Preelaboration rules, and might cause trouble
in (language) maintenance. That would look like:

(2) Add after 10.2.1(15.6/2) something like:

A generic unit is pure only if elaboration of the corresponding unit of an
instance would not perform any such actions.

Which one do you prefer? I'll make another AI for this one. Sigh.

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

From: Randy Brukardt
Date: Friday, January 12, 2007  8:45 PM

You'd think I was getting paid by the number of holes I find...

AI95-0002 changes the rules to exclude some subunits of preelaborated units to be
not require preelaboration.

Shouldn't that change also have been made to 10.2.1(17/2) for pure units?? The
same considerations would appear to apply, even though "pure" is never mentioned
by the AI or any discussion that I could find.

In particular, should a package subunit of a pure subprogram be required to be
pure? I don't think so; it's not elaborated by the elaboration of the pure subprogram.

I'll add that to the other pure issue.

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


Questions? Ask the ACAA Technical Agent