Version 1.12 of ai05s/ai05-0052-1.txt

Unformatted version of ai05s/ai05-0052-1.txt version 1.12
Other versions for file ai05s/ai05-0052-1.txt

!standard 4.8(5.3/2)          08-07-07 AI05-0052-1/10
!standard 7.5(8)
!class binding interpretation 07-05-15
!status work item 08-05-21
!status ARG Approved 7-0-1 08-02-09
!status work item 07-05-15
!status received 07-05-14
!priority Medium
!difficulty Hard
!qualifier Omission
!subject Coextensions and distributed overhead
!summary
Statically reject an allocator used to create a coextension if the designated type is limited but the enclosing object might be of a nonlimited type.
The term "immutably limited type" is introduced to simplify the presentation of this and other legality rules.
All of the legality rules of 4.8 apply in the private part of an instance.
!question
First:
In the case of a call to a function with a class-wide nonlimited result type, or of a dispatching call to a function with a nonlimited controlling result type, the current language definition seems to impose a substantial distributed overhead requirement in order to cope with the (typically remote) possibility that the function result might have a coextension with a task part.
This expense is incurred even if the program never allocates any such coextension.
Was this intended? (No.)
Second, in an apparently unrelated topic:
In an instance, 12.3(11) says that the Legality Rules are normally checked in the visible part of an instance, but not the private part. However, there are lots of Legality Rules that the RM says are also checked in the private part.
Should 4.8(5.1) be one of those? It looks like a possible oversight that it isn't.
package Pak1 is
type Root is tagged null record; type Root_Acc is access all Root'Class;
generic type T is new Root with private; Init : T; package Gen_Pack is private X : Root_Acc := new T' (Init); end Gen_Pack;
end Pak1;
with Pak1; procedure Proc1 is type Child is new Pak1.Root with record ... end record; Child_Init : constant Child := ...; package Inst is new Pak1.Gen_Pack (Child, Child_Init); begin ... end Proc1;
With the current wording of the Standard, it appears that the instance would be illegal if X were in the visible part of Gen_Pack; but with X in the private part, the program is legal but will raise an exception at runtime. There doesn't seem to be a good reason for this difference, is it intentional? (No.)
!recommendation
(See summary.)
!wording
Modify 4.8(5.3/2) as follows:
An allocator shall not be of an access type for which the Storage_Size has been specified by a static expression with value zero or is defined by the language to be zero. [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.] This rule does not apply in the body of a generic unit or within a body declared within the declarative region of a generic unit, if the type of the allocator is a descendant of a formal access type declared within the formal part of the generic unit.
{If the designated type of the type of the allocator is limited, then the allocator shall not be used to define the value of an access discriminant, unless the discriminated type is immutably limited (see 7.5).}
{AARM Note: Because coextensions work very much like parts, we don't want users creating limited coextensions for nonlimited types. This would be similar to extending a nonlimited type with a limited component. We check this on the allocator. Note that there is an asymmetry in what types are considered limited; this is required to preserve privacy. We have to assume that the designated type might be limited as soon as we see a limited partial view, but we want to ensure that the containing object is of a type that is always limited.}
{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.}
Add after 7.5 (8):
A type is immutably limited if it is one of the following:
* An explicitly limited record type;
* A non-formal limited private type that is tagged or has at least one access discriminant with a default_expression;
* A task type, a protected type, or a synchronized interface;
* A type derived from an immutably limited type.
AARM Discussion: An immutably limited type is a type that cannot become nonlimited subsequently in a private part or in a child unit. If a view of the type makes it immutably limited, then no copying (assignment) operations are ever available for objects of the type. This allows other properties; for instance, it is safe for such objects to have access discriminants that have defaults or designate other limited objects.
AARM Ramification: A non-synchronized limited interface is not immutably limited; a type derived from it can be nonlimited.
A descendant of a generic formal limited private type is presumed to be immutably limited except within the body of a generic unit or a body declared within the declarative region of a generic unit, if the formal type is declared within the formal part of the generic unit.
AARM Ramification: In an instance, a type is descended from the actual type corresponding to the formal, and all rules are rechecked in the specification. Bodies are excepted so that we assume the worst there; the complex wording is required to handle children of generics and unrelated bodies properly.
!discussion
Consider the following example:
package Pkg is type T1 is tagged null record; function F return T1'Class; end Pkg;
package body Pkg is task type Tsk; task body Tsk is separate; type T2 (Task_Ref : access Tsk) is new T1 with null record; function F return T1'Class is begin return T2'(Task_Ref => new Tsk); end F; end Pkg;
with Pkg; procedure Pkg_Client is X : Pkg.T1'Class := Pkg.F; begin null; end;
A function return object and its coextension have the same master (see 3.10.2(10.1/2)). Ada 2005 introduced access discriminants for nonlimited types.
This means that a call to a function which returns a nonlimited class-wide type or a dispatching call to a function with a nonlimited controlling result type must be able to cope with the possibility that the function result will include dependent tasks. The runtime overhead associated with this is likely to be significant, even if the compiler optimizes for the common case where no such tasks are returned. This is a heavy price to pay for such a rarely-used feature. Users may be displeased when recompiling an Ada95 program as an Ada2005 program generates worse code.
In the case of the preceding example, some kind of restriction is needed if a caller of Pkg.F is to be able to assume that it does not need to cope with tasks. The other choice, of course, is to leave the language unchanged and simply pay the performance cost for this feature.
Informally, an object's coextension can be thought of as being a "part" of of the object. This is the model that the language designers had in mind.
An extension of a nonlimited type cannot add a limited component. Leaning on our informal definition of "part" as it relates to coextensions leads to the conclusion that an extension of a nonlimited type should not have an access discriminant which designates a limited type, or at least that such an access discriminant should not designate a coextension. Checking rules like these is problematical, because it is not always known whether or not a type is limited. Consider, for example, a generic body which allocates a coextension for an object of a formal limited type; the corresponding actual type might or might not be limited.
Another possible approach would be to disallow access-to-limited non-inherited access discriminants for a nonlimited extension unless the parent type already has such a discriminant. The general idea is to require the decision about the legality of task "parts" for a nonlimited type to be made when the nonderived root of the derivation hierarchy is declared.
The easiest solution would be a runtime check when a coextension is allocated which fails if the coextension's type has a part that is of a task, protected, or explicitly limited record type and the owning object's type does not. In the case of the preceding example, this check would raise an exception at the point of the allocator within Pkg.F. For implementations which do not generate shared code for generics, the outcome of this check would always be known at code-generation time.
However, we generally prefer compile-time checks to runtime checks, especially in cases where there is no acceptable implementation. Thus, we prefer a static check. In order to avoid rejecting useful types in the absence of coextensions, we chose to make a conservative check on the creation of coextensions, rather than limiting the kinds of allowable discriminants. It is perfectly reasonable to have a discriminant that accesses an existing task object, and there is no reason to disallow such constructs.
In order for the check to work, we have to make any coextension allocator for a type that might be limited illegal unless it is a coextension of a type that is known to be limited. That is, there cannot be a case where the real coextension type turns out to be limited and the real type of the type with the access discriminant is not limited.
Note that this rule is incompatible with Ada 95 in unusual cases; those where a coextension is created with a limited type (including limited private types) and the type with the discriminant is not known to be limited (a limited private type, the only case where an access discriminant is allowed on something that Ada 2005 could complete with a non-immutably limited type). Coextension use is rare enough that this is not that important.
As part of this rule, we have defined the term "immutably limited". We noticed at a recent meeting that we had a number of rules related to types that are always limited in any view, that these rules were complicated (and wrong in a number of instances), and thus it was determined that defining a term to increase the commonality of those rules was a good idea. "Immutably" was chosen after an intermably long discussion as the best choice of literally dozens that were proposed.
As part of that definition, we allow limited private types with access discriminants with defaults to be immutably limited. We did that because the full type must be immutably limited (by 3.7(10/2) or especially the rewritten version of AI-63). We could have just patched 3.7(10) (which inexplicably changed in the Amendment to exclude limited private types, which is a glaring unintentional incompatibility with Ada 95), but that would mean that some things that are legal could be made illegal simply by converting the type into a private type. That would be sending exactly the wrong message - we want people to use private types as much as possible.
For the second question, we note that the new rule would need to be checked in the private part of an instance, and 4.8(5.3/2) already has such wording.
The example in the question makes it clear that 4.8(5.1/2) also should be checked in the private part. There doesn't seem to be any benefit in postponing detection of an error from compile-time to run-time.
4.8(5.2/2) should also apply in the private part of an instance, for similar reasons to 4.8(5.1/2), and also just to avoid confusion of having different policies apply to different legality rules for a single entity (in this case, an allocator).
So, we factor out the "applies in the private part of an instance" wording into a separate paragraph that applies to all of the legality rules of 4.8.
!corrigendum 4.8(5.3/2)
Replace the paragraph:
An allocator shall not be of an access type for which the Storage_Size has been specified by a static expression with value zero or is defined by the language to be zero. 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. This rule does not apply in the body of a generic unit or within a body declared within the declarative region of a generic unit, if the type of the allocator is a descendant of a formal access type declared within the formal part of the generic unit.
by:
An allocator shall not be of an access type for which the Storage_Size has been specified by a static expression with value zero or is defined by the language to be zero. This rule does not apply in the body of a generic unit or within a body declared within the declarative region of a generic unit, if the type of the allocator is a descendant of a formal access type declared within the formal part of the generic unit.
If the designated type of the type of the allocator is limited, then the allocator shall not be used to define the value of an access discriminant, unless the discriminated type is immutably limited (see 7.5).
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.
!corrigendum 7.5(8)
Insert after the paragraph:
There are no predefined equality operators for a limited type.
the new paragraphs:
A type is immutably limited if it is one of the following:
A descendant of a generic formal limited private type is presumed to be immutably limited except within the body of a generic unit or a body declared within the declarative region of a generic unit, if the formal type is declared within the formal part of the generic unit.
!ACATS test
An ACATS B-Test is needed to check this rule.
!appendix

From private mail of Randy Brukardt replying to a query from Steve Baird
(the original author of this AI):

> So what do you think? Is there a real problem here?
> If so, then what solution would you prefer?

Ban coextensions. They're not worth it in any sense of the word.

As to a practical solution, I simply don't care. I'll only implement coextensions
in Janus/Ada if (a) virtually everything else is finished; and (b) there is an
actual demand for them [or for a formal validation that required them]. I truly
doubt that either (a) or (b) will ever occur, and the odds of both are even less.
Anyway, the point is that the issue doesn't affect us, so I don't think it makes
sense to talk about a solution.

Moreover, the implementation burden is not that high for Janus/Ada (it simply means
returning "Could_Be_Task" for all class-wide types) and using the same scheme as
used for limited returns. So I can't get too excited about it. True, there is a
distributed overhead, but since the real issue of such overhead comes from controlled
types (which we have to assume are present for class-wide types) and from the
possibility of coextentions of any sort (in the absence of a ban), it just isn't
that much more. We might have to add some more stuff to the "stub" tasking system
(used for programs that don't have any tasks, but do have generics or other things
that *might* use a task, and thus have some [meaningless] task operations).

As such, I don't see much point in adding a restriction here. But I realize that
other implementations may have much more serious issues. Net-net: I can't endorse
anything for this issue.

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

!topic Should 4.8(5.1) be checked in the private part of an instance?
!reference RM05 4.8(5.1), 12.3(11)
!from Adam Beneschan 08-01-10
!discussion

In an instance, 12.3(11) says that the Legality Rules are normally
checked in the visible part of an instance, but not the private part.
However, there are lots of Legality Rules that the RM says are also
checked in the private part.  

Should 4.8(5.1) be one of those?  It looks like a possible oversight
that it isn't.

    package Pak1 is

       type Root is tagged null record;
       type Root_Acc is access all Root'Class;

       generic
          type T is new Root with private;
          Init : T;
       package Gen_Pack is
       private
          X : Root_Acc := new T' (Init);
       end Gen_Pack;

    end Pak1;


    with Pak1;
    procedure Proc1 is
       type Child is new Pak1.Root with record ... end record;
       Child_Init : constant Child := ...;
       package Inst is new Pak1.Gen_Pack (Child, Child_Init);
    begin
       ...
    end Proc1;

It appears that the instance would be illegal if X were in the visible
part of Gen_Pack; but with X in the private part, the program is legal
but will raise an exception at runtime.  There doesn't seem to be a
good reason for this.  (GNAT rejects this program, by the way.)

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

From: Randy Brukardt
Sent: Thursday, January 10, 2008  9:06 PM

> In an instance, 12.3(11) says that the Legality Rules are normally
> checked in the visible part of an instance, but not the private part.
> However, there are lots of Legality Rules that the RM says are also
> checked in the private part.

I don't think there is much doubt that we got the default wrong on this; it
should always be checked in the private part unless there is a rule that
says it is not. But it is waaayyy too late to make that kind of change.

> Should 4.8(5.1) be one of those?  It looks like a possible oversight
> that it isn't.

Most certainly. There are probably only a handful of rules in the entire
standard that it shouldn't apply to. Of course, there are many where it does
not matter either way.

>     package Pak1 is
>
>        type Root is tagged null record;
>        type Root_Acc is access all Root'Class;
>
>        generic
>           type T is new Root with private;
>           Init : T;
>        package Gen_Pack is
>        private
>           X : Root_Acc := new T' (Init);
>        end Gen_Pack;
>
>     end Pak1;
>
>
>     with Pak1;
>     procedure Proc1 is
>        type Child is new Pak1.Root with record ... end record;
>        Child_Init : constant Child := ...;
>        package Inst is new Pak1.Gen_Pack (Child, Child_Init);
>     begin
>        ...
>     end Proc1;
>
> It appears that the instance would be illegal if X were in the visible
> part of Gen_Pack; but with X in the private part, the program is legal
> but will raise an exception at runtime.  There doesn't seem to be a
> good reason for this.  (GNAT rejects this program, by the way.)

I suspect GNAT is just following good sense here.

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

From: Pascal Leroy
Sent: Friday, January 11, 2008  1:35 AM

I can't verify this, but I suspect that the IBM compiler also rejects this code.

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

From: Edmond Schonberg
Sent: Monday, February 4, 2008  1:20 PM

> [Is it time to define "inherently limited" in the RM?  I'd like to replace the
> first two bullets with, "If the type of the newly-created object is inherently
> limited, or has controlled parts, the anonymous object is built in place."
> That's not quite the same thing -- it requires b-i-p in more cases than the
> current RM.]

Yes, this is AI-52, for which I sent an update on Saturday night.   
Proposed definition:

Add after  7.5 (6.1/2):

A type is inherently limited if it is one of the following:

a) An explicitly limited record

b) A tagged limited private type

c) A task type, a protected type, or a synchronized interface.

d) A type derived from an inherently limited type.

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

From: Gary Dismukes
Sent: Monday, February 4, 2008  1:20 PM

It seems that the list should also include types that have a part
that is of an inherently limited type.

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

From: Robert A. Duff
Sent: Monday, February 4, 2008  2:48 PM

> > A type is inherently limited if it is one of the following:
...

Is it intended to be a property of a type, or a property of a view of a type?

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

From: Edmond Schonberg
Sent: Monday, February 4, 2008  2:59 PM

Most definitely a property of a type, but  one that can be determined  
by a partial view alone.

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

From: Edmond Schonberg
Sent: Monday, February 4, 2008  3:00 PM

> It seems that the list should also include types that have a part
> that is of an inherently limited type.

You're right, I thought that fell out automatically, but it doesn't,  
so it has to be added to the list.

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

From: Tucker Taft
Sent: Monday, February 4, 2008  3:20 PM

I don't quite understand the requirement to be
determinable from the partial view.  What about
an untagged limited private type?  You really
don't know anything about the full type.

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

From: Randy Brukardt
Sent: Monday, February 4, 2008  8:51 PM

> Is it intended to be a property of a type, or a property of a
> view of a type?

To be used in Legality Rules, it generally will have to be a property of a
view of a type. (Else we would break privacy.) As such, the definition may
not be appropriate for dynamic rules.

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

From: Randy Brukardt
Sent: Monday, February 4, 2008  9:01 PM

> I don't quite understand the requirement to be
> determinable from the partial view.  What about
> an untagged limited private type?  You really
> don't know anything about the full type.

Correct, and clearly such a view of a type is *not* inherently limited.
Anything else would break privacy for Legality Rules (which is what Ed is
using the term for). Thus it is clear this is a view-specific term.

More generally, the Standard is very confused about view vs. non-view (and
indeed we have an AI to fix this, at least in the sense of acknowledging that
the Standard is confused). I think that leads to *us* being confused about
what is a property of a view or a property of a type.


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

From: Edmond Schonberg
Sent: Monday, February 4, 2008  10:24 PM

> I don't quite understand the requirement to be
> determinable from the partial view.  What about
> an untagged limited private type?  You really
> don't know anything about the full type.

Precisely, that is not inherently limited, and thus cannot have an  
access discriminant whose designated type is limited.

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

Summary of editorial review discussion (May 2008):

Pascal Leroy:
I didn't study AI 52 very carefully, but I think it's disgggusting to
include formal types in "immutably limited" types. First, you are
lying about the work "immutably", and that makes any usage of term
confusing. It would be much better to say "immutably limited or descended
from a formal limited private type" when needed.  
 
Randy Brukardt:
This doesn't work, because of the body exception. It would have to be
"immutably limited or descended from a formal limited private type other
than in a generic body or a body nested in that body if the type is
declared in the specification of the body", and that would defeat the
entire purpose. It would get forgotten or done incorrectly - that was
the reason for introducing the term in the first place. We tried to
figure a name for this concept for a LONG time, and this is what we
came up with.

Pascal Leroy:
Well, I don't imagine how anyone would think of sending AI 52 to WG9
without any wording in this AI that tries to show how the term
"immutably limited" could be used in the rest of the RM.  The only
indication that this was even considered is a note in the minutes
that says: Steve Baird has volunteered himself to investigate what
other rules in the Standard could (and perhaps should) use "immutably
limited". There is not much point in defining this term if it is used
only once.

Randy Brukardt:
For the record, the term is also used in AI-54-2 and AI-59 (both
still open), AI-93 (that's Steve's homework, it just adds it in the
definition of "known to be constrained" from AI05-0008-1) and AI-53
(also going to WG9). The point is that we *did* consider how it was
going to be used in a large number of places, perhaps just not carefully
enough.
 
One could argue that the existence of so many places with slightly
different rules shows an existing language bug more than a feature.

Pascal Leroy:
Now you are going to tell me that it's also used in AI 63. But that's
exactly what worries me, because this AI causes is a significant
semantic: previously, a defaulted access discriminant was only
allowed by 3.7(10/2) in the cases that correspond to bullets 1, 2,
and 3 of the definition of "immutably limited". But now bullets 4
and 5 taken together make more cases legal. Consider:
 
generic
   type T is limited private;
package G is
   type R(D : access Integer := new Integer'(9)) is
      record
         X : T
      end record;
end G;
 
According to AI 52 type T is immutably limited in the generic
specification (bullet 4) and so is type R (bullet 5).  According to
AI 63, the defaulted access discriminant is legal.  This is very
strange: this generic was illegal in Ada 2005, but it is legal in
TC2. However, it cannot be instantiated with a nonlimited type
(instantiation rechecking will ensure this). What good does that do?
Ada is about detecting errors early, not about telling you on
instantiations that sorry, you cannot use this generic that way
(says someone who uses C++ templates daily). There is no indication
in the minutes or in the AI that this change was intended.
 
Incidentally, you'd have the same problem if you tried to use
"immutably limited" in the current instance rule in 3.10(9/2).

Randy Brukardt:
We did, in AI05-0053-1, which you didn't reach in your review.
 
Tucker Taft:
I agree the term "immutably limited" is somewhat problematic when
associated with formal limited types. Perhaps we simply need to
say that a formal limited type is *presumed* to be immutably limited
in the generic spec (but rechecked in the instance), rather than
saying that it *is* immutably limited. In the body, it is *not*
considered immutably limited if an actual type might not be immutably
limited.

Hence, with a relatively minor wording fix we could preserve the
generality of the term, but avoid misleading users into thinking that
formal limited types *require* that the actual be immutably limited,
unless there is a use in the spec that requires that.

Possible fix to wording:

  A type is *immutably limited* if it is one of the following:

  *  A descendant of an explicitly limited record type;

  *  A descendant of a non-formal tagged limited private type;

  *  A descendant of a task type, a protected type, or a synchronized interface;

  *  A type with a part that is of an immutably limited type.

  Within the declaration of a generic unit having a
  parameter that is a formal limited private type, any
  descendant of the formal type is presumed to be
  immutably limited.  Any legality rule that requires
  a type be immutably limited also applies in the
  private part of a generic instance.

-----------

I realize this wording is a bit unorthodox. Perhaps it can be rephrased
to be more consistent with other similar situations.

Pascal Leroy:

This doesn't address my point that AI 52+63 makes some constructs legal
in TC2 that were illegal in Ada 2005. There is no indication in any
document that I have read that says that it was intended. In particular,
I draw your attention to 3.7(10.e/2) which makes it very clear that the
designers of Ada 95, in their infinite wisdom, decided that a type with
an immutably limited component was not itself immutably limited (and I
think they were right then, and wrong now).

Tucker Taft:

Sorry, I hadn't understood your point. Now I see and I agree there is
no need to give special "immutably limited" status to types that get
limitedness from their subcomponents.

So we could eliminate the fourth bullet.

At that point we might be able to eliminate the repetitive use of
"descendant" and move that to its own bullet. I remember we couldn't
factor out the descendant part originally for some reason, perhaps
because we were trying to factor out the "part" part.  Hence, this
would produce:

    A type is *immutably limited* if it is one of the following:

    *  An explicitly limited record type;

    *  A non-formal tagged limited private type;

    *  A task type, a protected type, or a synchronized
       interface;

    *  A descendant of an immutably limited type.

    Within the declaration of a generic unit having a
    parameter that is a formal limited private type, any
    descendant of the formal type is presumed to be
    immutably limited.  Any legality rule that requires
    a type be immutably limited also applies in the
    private part of a generic instance.

Randy Brukardt:

> Sorry, I hadn't understood your point. Now I see and I agree there is 
> no need to give special "immutably limited" status to types that get 
> limitedness from their subcomponents.

You probably were confused probably because it was quite different
that the original issue that Pascal raised. I think he originally
pointed at the wrong culprit, and that confused all of us initially.

I recall being unconfortable with the inclusion of "part" here, but
mainly because it made Is_Immutably_Limited change depending on the
view of the components, which seemed like it opened up the door for
anomolies. I tried to raise the point during the discussion in Florida,
but the conversation went in a different direction and I got too
engrossed in keeping minutes to persue it.

...
>     Within the declaration of a generic unit having a
>     parameter that is a formal limited private type, any
>     descendant of the formal type is presumed to be
>     immutably limited.  Any legality rule that requires
>     a type be immutably limited also applies in the
>     private part of a generic instance.

This last paragraph doesn't work right. It's missing the generic body
exception, for one thing. It should only be presumed to be immutably
limited in the specification of a generic unit, not in the body; and it
needs to take children into account. And the last part doesn't come
close to the normal boilerplate. Moreover, I don't think it is needed;
the rules already require that or it doesn't matter. And this isn't
always used in Legality Rules: 3.10(9/2) is static semantics, as is the
definition of "known to be constrained". So I suggest replacing the last
paragraph with:

    A descendant of a generic formal limited private type is
    presumed to be immutably limited except within the body
    of a generic unit or a body declared within the declarative
    region of a generic unit, if the type is declared within the
    formal part of the generic unit.

(We know that this last wording is the in the right order for generic bodies,
because we use variants of it in a number of other rules; inventing new wording
is likely to be error-prone, especially for cases this complex.)

-----------

The interesting question is whether any of the new rules (specifically the ones
in AI-52 and AI-08) need to include "parts" of an immutably limited type. (I
presume the existing rules got it right, so they shouldn't use "part", as noted
by Pascal.)

For AI-52, the operative part is:

If the designated type of the type of the allocator is limited, then the
allocator shall not be used to define the value of an access discriminant,
unless the discriminated type is immutably limited (see 7.5).

This seems to nicely echo the wording of 3.7(10/3), so it would be weird to
allow more here. Moreover, there isn't a compatibility concern with Ada 95:
the only access discriminants are for immutably limited types, so this rule
always would pass.

However, there's a problem: 3.7(10) allows access discriminants in private
types so long as the full type is immutably limited; that got lost in
Ada 2005's 3.7(10/2), and 3.7(10/3) just copies that. Tucker has an action item
to see if that needs a fix. Not sure whether that fix needs to be in the
definition of immutably limited or just in 3.7(10/3). If just 3.7(10/3) is
changed, then there is a possibility of an Ada 95 incompatibility -- but that
wouldn't be fixed by including parts anyway.

So, pending resolution of that issue, there doesn't seem to be any reason to
change this rule to include parts. Ada 95 didn't allow them, so there is
unlikely to be an issue.

For AI-08 (as updated by Steve's AI-93), the third bullet would be:

its type is immutably limited (see 7.5); or

Here, I don't think we want this changing when views of components change,
so I don't think it either should be changed. And parts were not included
in the original rule. Formal types will always be rechecked, so they can't
introduce any holes.

So I think that we're OK here.

I've updated the AI with these changes (excepting Tucker's action item).

Tucker Taft:

...
> This last paragraph doesn't work right. It's missing the generic body 
> exception, for one thing.

Ummm..., doesn't it say "Within the *declaration* of a generic unit..."?

 > ...It should only be presumed to be immutably limited
> in the specification of a generic unit, not in the body; and it needs 
> to take children into account.

I thought it was more straightforward to say where it was legal rather
than to say where it was illegal. But you are probably right that it
should be legal in the declaration of a child, presuming it gets
rechecked in the instance of the child. That begins to get complicated
enough that perhaps we should revert to the tried-and-true wording that
excludes the body, rather than includes the spec.

> ...
> (We know that this last wording is the in the right order for generic 
> bodies, because we use variants of it in a number of other rules; 
> inventing new wording is likely to be error-prone, especially for 
> cases this complex.)

Fair enough.
 

> ...
> However, there's a problem: 3.7(10) allows access discriminants in 
> private types so long as the full type is immutably limited; that got 
> lost in Ada 2005's 3.7(10/2), and 3.7(10/3) just copies that. Tucker 
> has an action item to see if that needs a fix. Not sure whether that 
> fix needs to be in the definition of immutably limited or just in 
> 3.7(10/3). If just 3.7(10/3) is changed, then there is a possibility 
> of an Ada 95 incompatibility -- but that wouldn't be fixed by including parts anyway.

In looking at this right now, I believe a fix is needed.
I see two alternatives:

    1) In 7.5 say that a limited private (untagged) type is immutably
       limited if it has an access discriminant with a default.
       Since we recheck 3.7 in the private part, we will make
       sure the full type is also immutably limited.

    2) In 3.7 say that a limited private (untagged) type may have
       a default expression for an access discriminant, even
       though it is not considered "immutably limited."

I tend to favor (1), even though it is somewhat of a self-fulfilling prophecy,
because it is more flexible for the user.


> Still, pending resolution of that issue, there doesn't seem to be any 
> reason to change this rule to include parts. Ada 95 didn't allow them, 
> so there is unlikely to be an issue.
> ...
> I've updated the AI with these changes (excepting Tucker's action item).

Can I consider the above my action item?

Randy Brukardt:

> In looking at this right now, I believe a fix is needed.
> I see two alternatives:
> 
>     1) In 7.5 say that a limited private (untagged) type is immutably
>        limited if it has an access discriminant with a default.
>        Since we recheck 3.7 in the private part, we will make
>        sure the full type is also immutably limited.
> 
>     2) In 3.7 say that a limited private (untagged) type may have
>        a default expression for an access discriminant, even
>        though it is not considered "immutably limited."
> 
> I tend to favor (1), even though it is somewhat of a self-fulfilling 
> prophecy, because it is more flexible for the user.

Humm. My first thought was yuck, but then I had to conclude that it probably
is OK - as you say, the full type will have to be an immutably limited type,
so there is no privacy breakage. (It's kinda a backdoor way to declare that,
but its compatible, while anything more explicit would be incompatible). And it
eliminates a potential landmine, particularly for the new AI-52 rule: an
allocator for a coextension of a non-private immutably limited type would
work, but restructure to use a private type and your coextension allocator
is illegal. That is exactly the wrong structuring message to send.

> > Still, pending resolution of that issue, there doesn't seem to be 
> > any reason to change this rule to include parts. Ada 95 didn't allow 
> > them, so there is unlikely to be an issue.
> > ...
> > I've updated the AI with these changes (excepting Tucker's action item).
> 
> Can I consider the above my action item?

Well, originally you needed a new AI to accomplish the above. However, since
Pascal has forced us to withdraw various AIs anyway, we might as well stick
the repair in AI-52. In which case I guess I can do your work for you.

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

From: Pascal Leroy
Sent: Wednesday, May 28, 2008  12:05 AM

Incidentally, I am a bit annoyed by the difference in terminology
between "immutably limited type" and "explicitly limited record type".
It would have been nice to use the same adverb somehow. But I suppose
that you guys have discussed this ad nauseum...

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

From: Tucker Taft
Sent: Wednesday, May 28, 2008  12:09 AM

We did get pretty nauseated during the discussion, if I remember
correctly.  Perhaps "nauseatingly limited" might have been a better
term... ;-)

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

From: Tucker Taft
Sent: Wednesday, May 28, 2008  12:19 AM

Perhaps with the slight tweak in the definition that you suggested,
by eliminating the dependence on "parts," we might be able to go to
something like "explicitly limited type," where "explicitly limited
record" is an obvious special case.  Might deserve some thought.

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

From: Pascal Leroy
Sent: Wednesday, May 28, 2008  12:30 AM

That crossed my mind too.  To some extent that terminology would work
better for formal types.  It seems to me that they are "explicitly limited"
('cause I can see the word "limited" there) but not "immutably limited"
('cause they can become unlimited in an instance).

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

From: Randy Brukardt
Sent: Wednesday, May 28, 2008  2:59 PM

But I would expect that calling task types, protected types, and
synchronized interfaces "explicitly limited" would offend your
French sensibilities. :-) No word "limited" to be seen in any of those.
Moreover, limited private types and limited interfaces would not be
"explicitly limited" even with the presence of the word "limited".
That seems too confusing to contemplate.

So I think is best to leave this sleeping dog lie. Especially as Tucker's
"presumed to be immutably limited" wording eliminates the discomfort on
formal types (and is more like other wording as well, seems like a win-win).

Just a reminder, here's the current wording for "immutably limited":

A type is *immutably limited* if it is one of the following:

    *  An explicitly limited record type;

    *  A non-formal limited private type that is tagged or has
       at least one access discriminant with a default_expression;

    *  A task type, a protected type, or a synchronized
       interface;

    *  A descendant of an immutably limited type.

A descendant of a generic formal limited private type is presumed to be
immutably limited except within the body of a generic unit or a body declared
within the declarative region of a generic unit, if the type is declared
within the formal part of the generic unit.

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

From: Tucker Taft
Sent: Wednesday, May 28, 2008  3:32 PM

I would suggest one tweak to the wording below:

...
> A descendant of a generic formal limited private type is presumed to 
> be immutably limited except within the body of a generic unit or a 
> body declared within the declarative region of a generic unit, if the 
> {*formal*} type is declared within the
                                     ^^^^^^^^
> formal part of the generic unit.

I think it is important to say the *formal* type since otherwise
we have an ambiguity as to whether we are talking about the "descendant"
or the "generic formal limited private type."

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

Questions? Ask the ACAA Technical Agent