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

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

!standard 3.4(5.1/2)          08-05-23 AI05-0096-1/01
!class binding interpretation 08-05-23
!status work item 08-05-23
!status received 06-05-21
!priority Medium
!difficulty Medium
!qualifier Omission
!subject Deriving from formal limited types
!summary
An instance of a generic is illegal if a limited type extension is derived from a formal tagged limited private type and the actual type is nonlimited.
!question
Consider the following:
generic type Lim is limited private; package Gen is ... private type New_Lim is limited new Lim; end Gen;
package New_Gen is new Gen (Integer);
The template is legal, but the instance seems to violate 3.4(5.1/2). However, that rule is not rechecked in the instance (it doesn't have the boilerplate wording for that), so this is legal. Is that intended?
!wording
Add to 3.4(5.1/2):
If the parent type is a tagged formal type, in addition to the places where Legality Rules normally apply (see 12.3), this rule applies also in the private part of an instance of a generic unit.
AARM Note: If the parent type is a untagged limited formal type with an actual type that is nonlimited, we allow derivation as a limited type in the private part or body as no place could have visibility on the resulting type where it was known to be nonlimited (outside of the instance). (See the previous paragraph's AARM notes for an explanation of this.) However, if the parent type is a tagged limited formal type with an actual type that is nonlimited, it would be possible to pass a value of the limited type extension to a classwide type of the parent, which would be nonlimited. That's too weird to allow (even though all of the extension components would have to be nonlimited because the rules of 3.9.1 are rechecked), so we have a special rule to prevent that in the private part (type extension from a formal type is illegal in a generic package body).
!discussion
As explained by AARM 3.4(5.b-f/2), 3.4(5/2) is one of the (very few) rules where we intentionally don't recheck the rule in the private part. Specifically, a similar example to that in the question:
generic type Lim is limited private; package Gen is ... private type New_Lim is new Lim; end Gen;
package New_Gen is new Gen (Some_Tagged_Type); -- OK!
is allowed because nothing can have a view that "knows" that New_Lim is a tagged type.
So it seems that the example in the question should also be allowed for similar reasons.
However, this is not true if the parent type is known to be a tagged type, because then we could pass a value of New_Lim to the class-wide type corresponding to the parent type. If that parent type is also nonlimited, we could then assign a limited tagged type.
--!corrigendum 3.4(5.1/2)
!ACATS Test
An appropriate example should be tested in an ACATS B-Test.
!appendix

From: Pascal Leroy
Sent: Thursday, May 22, 2008  12:24 AM

[From a private mail of an unrelated subject.]

Incidentally, I am wondering how 3.4(5.1/2) interacts with generics.  Shouldn't it
be rechecked in the private part of an instance?  Shouldn't it assume the worst in
a generic body?  Maybe it's a rule that ought to say "immutably limited".

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

From: Randy Brukardt
Sent: Friday, May 23, 2008  9:42 PM

I started to create an AI on this topic, but I've gotten less convinced that there is a
problem as I've looked at it. [And then more - read the whole message.]

First, let's discard the last sentence. Interfaces are never "immutably limited",
and the whole point of this feature was to allow the derivation of limited interfaces
to create new limited types. So if we required "immutably limited", these could never
be used for their intended purpose.

Second, rechecking in the private part. 3.4(5/2) does *not* require rechecking in
the private part. This one of the very, very few places where that was intentional.
(Indeed, itís the only one that comes to mind!) Consider:

   generic
       type Lim is limited private;
   package Gen is
       ...
   private
       type New_Lim is new Lim;
   end Gen;

   package New_Gen is new Gen (Some_Tagged_Type); -- OK!

This the only place in the language where it is legal to derive a tagged type without
a record extension. And that is considered OK because there is no place where New_Lim
could ever be viewed as a tagged type. (Similarly in the body of a generic.)
AARM 3.4(5.b/2 - 5.f/2) explains this.

3.4(5.1/2) is a very similar rule. Consider the very similar example:

   generic
       type Lim is limited private;
   package Gen is
       ...
   private
       type New_Lim is limited new Lim;
   end Gen;

   package New_Gen is new Gen (Integer); -- OK!

It seems that the same thinking should apply to this declaration: there is no location
where New_Lim could ever be seen as a non-limited type. So there doesn't seem to be
a problem. Similarly in the body.

However, there seems to be a possible problem with tagged types. 

   generic
       type Lim is tagged limited private;
   package Gen is
       ...
   private
       type New_Lim is limited new Lim with null record;
   end Gen;

   package New_Gen is new Gen (Some_Non_Limited_Tagged_Type); -- Ouch.

A declaration like New_Lim is illegal in a generic body by 3.9.1(4/2). And the
automatic recheck in the spec will make this illegal in the visible part. But
here in the private part, we have a case where where we have a limited tagged type
derived from a non-limited tagged type. Obviously, a class-wide operation of
Some_Non_Limited_Tagged_Type could assign a value of New_Lim.

However, even here I can't see a actual problem (although this is very weird).

   generic
       type Lim is tagged limited private;
   package Gen is
       ...
   private
       type New_Lim is limited new Lim with record
            Tsk : A_Task;
       end record;
   end Gen;

   package New_Gen is new Gen (Some_Non_Limited_Tagged_Type); -- Illegal.

3.9.1(3/2) says "if the parent type is nonlimited, then the components shall
be nonlimited", and is rechecked in the private part of the instance. Since
Lim is nonlimited in the instance, this declaration is illegal.

So the only extension components could be nonlimited, so assignment is available
for every component of New_Lim.

Still, this seems too weird for words. So I suggest adding a recheck rule for
tagged types only:

"If the parent type is a tagged type, in addition to the places where
Legality Rules normally apply (see 12.3), this rule applies also in the
private part of an instance of a generic unit."

AARM Note: If the parent type is a nonlimited untagged type, we allow derivation
as a limited type in the private part or body as no place could have visibility
on the resulting type where it was known to be nonlimited (outside of the instance).
(See the previous paragraph's AARM notes for an explanation of this.) However, if the
parent type is tagged, it would be possible to pass a value of the limited type
extension to a classwide type of the parent, which would be nonlimited. That's
too weird to allow (even though all of the extension components would have to be
nonlimited because the rules of 3.9.1 are rechecked), so we have a special rule
to prevent that in the private part (type extension from a formal type is illegal
in a generic package body).

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


Questions? Ask the ACAA Technical Agent