Version 1.3 of ai05s/ai05-0017-1.txt

Unformatted version of ai05s/ai05-0017-1.txt version 1.3
Other versions for file ai05s/ai05-0017-1.txt

!standard 13.14(3/1)          07-06-17 AI05-0017-1/03
!class binding interpretation 06-11-09
!status ARG Approved 7-0-3 07-06-03
!status work item 06-11-09
!status received 06-08-02
!priority High
!difficulty Medium
!qualifier Omission
!subject Freezing and incomplete types
!summary
The rules that define how package bodies freeze Taft-Amendment types are modified to eliminate anomalies.
!question
The second sentence of 13.14(3/1) states that "A noninstance body other than a renames-as-body causes freezing of each entity declared before it within the same declarative_part".
Consider the following:
procedure Foo is
package P1 is
private
type T1;
end P1;
package P2 is
private
type T2;
end P2;
package body P1 is separate; package body P2 is separate;
begin
...
end Foo;
The rule here seems to say that the stub for P1 freezes both T1 and T2. T1 surely cannot be meant to be frozen here (else an incomplete type deferred to a body could never work - which would violate Dewar's rule). But freezing T2 is also problematic. Do we really want the stub for P1 to freeze T2 (and thereby make the above program illegal)? (No.)
!recommendation
(See Summary.)
!wording
Modify 13.14(3/1):
The end of a declarative_part, protected_body, or a declaration of a library package or generic library package, causes freezing of each entity declared within it, except for incomplete types. A noninstance body other than a renames-as-body causes freezing of each entity declared before it within the same declarative_part {that is not an incomplete type; it only causes freezing of an incomplete type if the body is within the immediate scope of the incomplete type.}
!discussion
We do need to have freezing of incomplete types, because that helps to prevent premature uses in calls. Consider the following:
package Stt is
type T is tagged; function F return access T'Class; function G (X : access T) return Integer; I : Integer := G (F); type T is tagged null record;
end Stt;
The call to G is dispatching, so we better know the location of the tag for type T. The profile of G is frozen, which freezes the anonymous access type and its designated type, which is T, which is not completed yet, and that violates 13.14(17) (or 3.11.1(8) if you prefer) and an error will occur. If we didn't freeze incomplete types, this error would not be detected and we'd have a problem.
We don't want an intervening body to freeze any deferred incomplete types, otherwise they'd be useless. Moreover, there is no need to freeze them -- their representation is not needed until their own body is encountered, because there are numerous restrictions on the usages of such types (see 3.10). So we adjust the wording to avoid unnecessary freezing.
The new wording is supposed to have no effect for "ordinary" incomplete types, that is, types for which the incomplete_type_declaration and the full_type_declaration occur in the same list of declarations. For such types, a noninstance body causes freezing.
The new wording is also supposed to have no effect for bodies that are within the immediate scope of the (incomplete) type. For instance, a subprogram body nested within the body of the package that declares the type causes freezing.
The new wording says, however, that bodies that don't have visibility to a Taft-Amendment type do not cause freezing of this type. This means that, in the example, the stub for P1 doesn't freeze P2.T2. Similarly the beginning of the body of P1 doesn't freeze P1.T1, otherwise it would be impossible to write a Taft Amendment type.
Note that the start of the package body P1 does not cause freezing of T1, but the end of the declarative part of the package body will freeze everything including T1. That happens because the body P1 must necessarily include a completion for T1, which will be frozen at the end, and that freezing will also freeze the incomplete view (remember that types are frozen, not views). If there is no completion, P1 is illegal anyway, so we don't care that the incomplete T1 never gets frozen in that case.
Note that new rules don't have issues with premature uses in calls, as a Taft-Amendment type cannot be used in a primitive subprogram for the type [3.10.1(9.3/2)] (meaning that there cannot be primitive subprograms for a T-A type [of course, the full type can have primitive subprograms]). Since there are no subprograms, there aren't any calls to worry about.
!corrigendum 13.14(3/1)
Replace the paragraph:
The end of a declarative_part, protected_body, or a declaration of a library package or generic library package, causes freezing of each entity declared within it, except for incomplete types. A noninstance body other than a renames-as-body causes freezing of each entity declared before it within the same declarative_part.
by:
The end of a declarative_part, protected_body, or a declaration of a library package or generic library package, causes freezing of each entity declared within it, except for incomplete types. A noninstance body other than a renames-as-body causes freezing of each entity declared before it within the same declarative_part that is not an incomplete type; it only causes freezing of an incomplete type if the body is within the immediate scope of the incomplete type.
!ACATS test
Existing ACATS tests cover the basic cases. A C-test similar to the example in the question should be added.
!appendix

From: Pascal Leroy
Date: Wednesday, August 2, 2006  4:36 AM

The second sentence of 13.14(3/1) states that "A noninstance body other
than a renames-as-body causes freezing of each entity declared before it
within the same declarative_part".

Taken at face value this rule would mean that the following is illegal:

	procedure Foo is
	   package P is
	   private
	      type T;
	   end P;

	   package body P is
	      type T is new Boolean;
	   end P;
	begin
	   ...
	end Foo;

because the body of P would freeze type T, which is incompletely defined.
But I am willing to abide by Dewar's Law and to pretend that the RM
doesn't say this because it's absurd.

However I am troubled by the effect of this same rule if two packages are
involved:

	procedure Foo is
	   package P1 is
	   private
	      type T1;
	   end P1;
	   package P2 is
	   private
	      type T2;
	   end P2;

	   package body P1 is separate;
	   package body P2 is separate;
	begin
	   ...
	end Foo;

The rule here says that the stub for P1 freezes both T1 and T2.  Ignore T1
since it's surely not meant to be frozen by the stub for P1.  Do we really
want the stub for P1 to freeze T2 (and thereby make the above program
illegal)?  The freezing problem can be circumvented by moving the stub for
P1 before the specification of P2, but this doesn't help if the proper
body of P1 needs visibility to P2.

It seems to me that the wording is unnecessarily restrictive here, to the
point where it might be incompatible with Ada 83 (although it's always
hard to know how freezing works in Ada 83).  I think that the above rule
should make an exception for Taft-amendment types, although I must admit
that I am nervous with the notion of tweaking the freezing rules.

Comments?

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

From: Tucker Taft
Date: Wednesday, August 2, 2006  6:55 AM

My assumption is that freezing an incomplete view of a type
has no effect.

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

From: Pascal Leroy
Date: Wednesday, August 2, 2006 10:08 AM

Nice theory, but there is no support for it in the words of the RM.  Note
in particular 13.14(17) which says "A type shall be completely defined
before it is frozen".  I see nothing in the freezing rules that makes
special provisions for incomplete types, except for the first sentence of
13.14(3/1) which is intended to support Taft-amendment types.

I don't think that you can rely on the restrictions on the usage of
incomplete types in 3.10.1 to ensure that you don't have problems: you
really need the freezing rules.

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

From: Tucker Taft
Date: Wednesday, August 2, 2006 10:46 AM

> Nice theory, but there is no support for it in the words of the RM.  Note
> in particular 13.14(17) which says "A type shall be completely defined
> before it is frozen".  I see nothing in the freezing rules that makes
> special provisions for incomplete types, except for the first sentence of
> 13.14(3/1) which is intended to support Taft-amendment types.

Yes, sorry, I didn't mean to imply the wording was already
correct.  I was suggesting that what it *should* says is
that incomplete views are never frozen, or freezing has no
effect.  And 13.14(17) should probably restrict itself to
requiring that freezing a non-incomplete view shall happen
only after the type is completely defined.

> I don't think that you can rely on the restrictions on the usage of
> incomplete types in 3.10.1 to ensure that you don't have problems: you
> really need the freezing rules.

Can you explain this further?  What do you expect it to
mean to freeze an incomplete view?  Or are you saying that
there should never be an incomplete view visible inside
a body?  That is already possible in Ada 95, because a
child has visibility on the private part of its parent
where there might be an incomplete type declaration.

Freezing is supposed to ensure that the layout has
been decided before you start generating code that depends
on the layout.  But for incomplete views, we don't
know anything about the type, except perhaps that it
is tagged, and all we can do with it is manipulate an access
value designating the incomplete view.  Is freezing
relevant here?

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

From: Pascal Leroy
Date: Wednesday, August 2, 2006 11:09 AM

> Yes, sorry, I didn't mean to imply the wording was already 
> correct.  I was suggesting that what it *should* says is that 
> incomplete views are never frozen, or freezing has no effect. 
>  And 13.14(17) should probably restrict itself to requiring 
> that freezing a non-incomplete view shall happen only after 
> the type is completely defined.

I'd be happy to go that way for Taft-amendment types, which come with
strong restrictions, and are mostly invisible except for child units.  I'd
be reluctant to do it for all incomplete types, see below.

> Can you explain this further?  What do you expect it to
> mean to freeze an incomplete view?  Or are you saying that 
> there should never be an incomplete view visible inside a 
> body?  That is already possible in Ada 95, because a child 
> has visibility on the private part of its parent where there 
> might be an incomplete type declaration.
> 
> Freezing is supposed to ensure that the layout has
> been decided before you start generating code that depends
> on the layout.  But for incomplete views, we don't
> know anything about the type, except perhaps that it
> is tagged, and all we can do with it is manipulate an access 
> value designating the incomplete view.  Is freezing relevant here?

One delicate problem with (tagged) incomplete tags is that you need to
know the location of the tag in order to generate code for a dispatching
call.  This is similar to a dereferencing, except that there is stricto
sensu no implicit or explicit dereferencing.  In fact we added a number of
restrictions in the Amendment to plug holes in this area (see
3.10.1(9.3/2) for instance, and the discussion of AI 326 in the minutes of
the San Diego meeting).

If a body were allowed to see an incomplete view, I would be concerned
about similar problems.  It seems simpler and safer to maintain the
invariant that a body never sees an incomplete view.

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

From: Tucker Taft
Date: Wednesday, August 2, 2006 11:36 AM

But I don't see how using the freezing rules to enforce
that makes sense.  The only non "Taft-amendment" incomplete
types potentially visible in a body would be those made
visible via limited with (or am I missing something?),
presumably inherited from the spec. For those, how can you
use freezing rules to freeze something declared in a
different library unit?

My belief is that we need to have rules that properly restrict
use of limited tagged types, and in particular, don't allow
controlling operands to be incomplete.  I don't see this
as related to the freezing rules.

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

From: Pascal Leroy
Date: Wednesday, August 2, 2006 11:56 AM

> But I don't see how using the freezing rules to enforce
> that makes sense.  The only non "Taft-amendment" incomplete 
> types potentially visible in a body would be those made 
> visible via limited with (or am I missing something?), 

One of us is confused.  Consider:

	procedure Main is
	   type T is tagged;
	   procedure P is separate;
	   type T is tagged null record;
	   ...
	end Main;

I believe you said earlier that the stub for P should not freeze T.  In
this case, I'd be concerned about someone in the body of P having to know
the location of the tag to perform a dispatching call (I don't have a
precise example, though).

> My belief is that we need to have rules that properly 
> restrict use of limited tagged types, and in particular, 
> don't allow controlling operands to be incomplete.  I don't 
> see this as related to the freezing rules.

(You mean "incomplete tagged types" above, or else I am lost.)

Currently the only rule that tries to prevent incomplete controlling
operands is 3.10.1(9.3), which is specific to Taft-amendment types.  When
this rule was designed, I was under the impression that Taft-amendment
types were the only possible cause of trouble, because the freezing rules
would catch any attempt to make a dispatching call for other incomplete
types.  This may have been wrong, and it is possible that there are
problems specific to limited views, but for vanilla incomplete types I
think that the freezing rules help a lot.

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

From: Robert I. Eachus
Date: Wednesday, August 2, 2006  1:34 PM

Summary: Probably not worth reading all of this, but I wrote it to get 
my thoughts straight.  It turns out that the only real problems occur 
with Taft amendment types, and they can be resolved by saying that a 
package body causes freezing, but at the end of the body itself.  Things 
inside the package body can cause earlier freezing.

Pascal Leroy wrote:

>The second sentence of 13.14(3/1) states that "A noninstance body other
>than a renames-as-body causes freezing of each entity declared before it
>within the same declarative_part".
>
>Taken at face value this rule would mean that the following is illegal:
>
>	procedure Foo is
>	   package P is
>	   private
>	      type T;
>	   end P;
>
>	   package body P is
>	      type T is new Boolean;
>	   end P;
>	begin
>	   ...
>	end Foo;
>
>because the body of P would freeze type T, which is incompletely defined.
>But I am willing to abide by Dewar's Law and to pretend that the RM
>doesn't say this because it's absurd.
>
>However I am troubled by the effect of this same rule if two packages are
>involved:
>
>	procedure Foo is
>	   package P1 is
>	   private
>	      type T1;
>	   end P1;
>	   package P2 is
>	   private
>	      type T2;
>	   end P2;
>
>	   package body P1 is separate;
>	   package body P2 is separate;
>	begin
>	   ...
>	end Foo;
>
>The rule here says that the stub for P1 freezes both T1 and T2.  Ignore T1
>since it's surely not meant to be frozen by the stub for P1.  Do we really
>want the stub for P1 to freeze T2 (and thereby make the above program
>illegal)?  The freezing problem can be circumvented by moving the stub for
>P1 before the specification of P2, but this doesn't help if the proper
>body of P1 needs visibility to P2.
>
>It seems to me that the wording is unnecessarily restrictive here, to the
>point where it might be incompatible with Ada 83 (although it's always
>hard to know how freezing works in Ada 83).  I think that the above rule
>should make an exception for Taft-amendment types, although I must admit
>that I am nervous with the notion of tweaking the freezing rules.
 

I understand the rest of the discussion, but let's not lose the original 
reason for the question.  It seems to me that there are two questions 
here.   The first example can easily be dealt with by stating explicitly 
(or assuming) that the freezing caused by a package body is an effect of 
the unit as a whole.  Thus a freezing, or a definition, or a 
representation pragma can occur within a  body.  However a better rule 
would be that a package body freezes any objects named in the body.

The issue in the second case is more difficult.   Ignoring the Taft 
amendment issues for the moment, we have a separate unit causing 
freezing. Where separate units are involved, the 'better rule' above 
would not work.  So the issue, at least to me, seems to be a tradeoff 
between a desire to have separate unints not affect semantics, and the 
advantages (if any) of avoiding gratuitous freezing.  Let me create an 
example that doesn't involve Task amendment types:

	package Foo is
           type T1 is private;
	   package P1 is...; --left undefined for now.
           ...
	private
           ...
           type T1 is ... -- legal? (not illegal due to P1.
	end Foo;

I can think of lots of software that looks exactly like this where P1 is
used to export operations on the (non-Ada) abstract type T1. The declarations
in P1 won't freeze T1, and everything is okay--until we put in a a package
body. This can't occur in a package specification, but it can in a package
body or subprogram body:

	package body Foo is
           type T2;
           ...
	   package body P1 is...; -- operations on T1
           type T2 is... -- illegal? (seems that way)
	end Foo;

Can gratuitously freezing T2 here cause problems?  Yes, but I think the right
solution may be to move one declaration of T2, either the incomplete declaration
or the completion.  First the potential problem.  The body of P1 may need to
occur early so that it can make calls to subroutines that will either be hidden
by the full declaration of T2, or more likely, to avoid ambiguity and name
resolution issues.  Why not move the incomplete declaration after the body?
Taft amendment types create one situation where this is not possible, but moving
the completion earlier seems to work in all cases.

As for the 'better solution': There are many statements or declarations that
could occur inside P1 to cause freezing of T1, I think that those rules are
right and necessary, and in any case are not at issue here. In cases where P1
does not depend on T1, reording the declarations should always work.

If we were back in 2003 or so, I might argue for the 'better solution' above.
 But since the standard has been approved as written, I think a ramification
that the freezing occurs at the end of the body is the best solution.

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

From: Edmond Schonberg
Date: Wednesday, August 2, 2006  2:11 PM

> Summary: Probably not worth reading all of this, but I wrote it to  
> get my thoughts straight.  It turns out that the only real problems  
> occur with Taft amendment types, and they can be resolved by saying  
> that a package body causes freezing, but at the end of the body  
> itself.  Things inside the package body can cause earlier freezing.

Changing the freezing rules in such a radical way at this point is  
totally out of the question. For the last 10 years  (make that 11) we  
have read the freezing rules to mean that before analysis of a body  
can start, all previous entities in the current declarative part are  
frozen.  The current problem involves only incomplete types that are  
limited views, and I have not yet seen an example that would not be  
illegal because of other rules. If there is a problem, it must have a  
very local fix.

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

From: Pascal Leroy
Date: Thursday, August 3, 2006  3:05 AM

I actually think that the problems have to do with Taft-amendment types,
not with types in limited views.  But other than that, I entirely agree
with Ed.  We want localized fixes to plug holes, not a grandiose redesign
of the freezing rules (such a redesign was already out of bounds for the
2005 Amendment, btw, so I would have taken the same position in 2003).

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

From: Tucker Taft
Date: Wednesday, August 2, 2006  5:01 PM

> One of us is confused.

I think I was.

> ... Consider:
> 
> 	procedure Main is
> 	   type T is tagged;
> 	   procedure P is separate;
> 	   type T is tagged null record;
> 	   ...
> 	end Main;
> 
> I believe you said earlier that the stub for P should not freeze T.  In
> this case, I'd be concerned about someone in the body of P having to know
> the location of the tag to perform a dispatching call (I don't have a
> precise example, though).

I agree that there is no need to rock the boat on this
one, and the above, if you omit the "is tagged" would
clearly be syntactically possible in Ada 95, and it would
presumably freeze T, and hence violate the freezing rules.
So perhaps all we are worried about are "Taft-amendment" (TA)
types, and a desire that they *not* be frozen by bodies
occurring outside the package body.  We certainly know that
that if a TA type is declared in the private part of P,
then the start of the body of P itself doesn't freeze TA,
or else how could TAs work at all?

The last sentence of 13.4(3/1) [he means 13.14(3/1) - Ed.] is currently:

    A noninstance body other than a renames-as-body causes freezing
    of each entity declared before it within the same declarative_part.

This is clearly broken as written, given the following piece
of Ada 95 code:

     procedure Main is
        package P is
            type A is private;
        private
            type T;
            type A is access T;
        end P;

        package body P is  -- does this freeze P.T?
            type T is new Integer;
        end P;

     begin
        null;
     end Main;

Clearly we need to augment the last sentence of 13.4(3/1) with
something like:

      ... of each entity declared before it within the same
      declarative_part, other than an incomplete type declared
      within a preceding package specification.

(or perhaps "nested" rather than "preceding"?)

>> My belief is that we need to have rules that properly 
>> restrict use of limited tagged types, and in particular, 
>> don't allow controlling operands to be incomplete.  I don't 
>> see this as related to the freezing rules.
> 
> (You mean "incomplete tagged types" above, or else I am lost.)
> 
> Currently the only rule that tries to prevent incomplete controlling
> operands is 3.10.1(9.3), which is specific to Taft-amendment types.  When
> this rule was designed, I was under the impression that Taft-amendment
> types were the only possible cause of trouble, because the freezing rules
> would catch any attempt to make a dispatching call for other incomplete
> types.  This may have been wrong, and it is possible that there are
> problems specific to limited views, but for vanilla incomplete types I
> think that the freezing rules help a lot.

Fair enough.  Do you agree with the above augmentation (or something
like it) for the last sentence of 13.4(3/1)?  I think my concern
about "limited-with" types is a red herring, as these are not
declared within the "same" declarative_part.

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

From: Pascal Leroy
Date: Thursday, August 3, 2006  5:27 AM

> I agree that there is no need to rock the boat on this
> one, and the above, if you omit the "is tagged" would
> clearly be syntactically possible in Ada 95, and it would 
> presumably freeze T, and hence violate the freezing rules. So 
> perhaps all we are worried about are "Taft-amendment" (TA) 
> types, and a desire that they *not* be frozen by bodies 
> occurring outside the package body.  We certainly know that 
> that if a TA type is declared in the private part of P, then 
> the start of the body of P itself doesn't freeze TA, or else 
> how could TAs work at all?

I agree with all this.

> Clearly we need to augment the last sentence of 13.4(3/1) 
> with something like:
> 
>       ... of each entity declared before it within the same
>       declarative_part, other than an incomplete type declared
>       within a preceding package specification.

Yes, that change, combined with the existing completion rules of
3.10.1(3), seem to achieve what we want.

> I think my concern about "limited-with" types is a red herring, 
> as these are not declared within the "same" declarative_part.

I think so too.  However, you got me thinking on the topic of dispatching
calls, and I ended up with the following example:

	package Stt is 
	    type T is tagged; 
	    function F return access T'Class; 
	    function G (X : access T) return Integer; 
	    I : Integer := G (F); 
	    type T is tagged null record; 
	end Stt;

The call to G is dispatching, so we better know the location of the tag
for type T.  But I am not sure if 13.14(14) helps, because I have always
interpreted "subtype of its profile" to mean the subtypes of the
parameters or result (access T or access T'Class here) not any random
subtype that happens to appear in the profile (like T here).  And
3.10.1(10/2) surely doesn't help because there is no prefix of an
incomplete view in sight.  It seems to me that the latter paragraph should
be augmented to deal with the "very implicit dereference" associated with
fetching the tag in a dispatching call.

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

From: Robert I. Eachus
Date: Thursday, August 3, 2006 10:33 AM

>The call to G is dispatching, so we better know the location of the tag
>for type T.
>
As written compilers will probably replace the call to G to initialize 
I with a raise of Program_Error.  I can't think offhand of an example 
where G is a generic instance and there is a problem, but there may be.

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

From: Pascal Leroy
Date: Friday, August 4, 2006  2:22 AM

> As written compilers will probably replace the call to G to 
> initialize I with a raise of Program_Error.

Maybe, maybe not, but that's irrelevant.  The rules of the language should
not depend on a compiler performing (or not performing) an optimization.
Furthermore, even if a compiler performs the optimization that you
describe, it might well do it in two phases: first generate the call, then
do some analysis of elaboration checks.  If the code generator fails
during the first phase because it cannot locate the tag, we have a
problem.

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

From: Edmond Schonberg
Date: Friday, August 4, 2006  9:25 AM

Which is exactly a problem I found in GNAT when trying your example.   
We now detect the illegal use of the access parameter further  
upstream, when analyzing the dispatching call. An instructive  
example!!  Fortunately the fix is extremely localized, and the  
freezing rules are unaffected.

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

From: Robert A. Duff
Date: Friday, August 4, 2006  9:18 AM

> > >	package Stt is 
> > >	    type T is tagged; 
> > >	    function F return access T'Class; 
> > >	    function G (X : access T) return Integer; 
> > >	    I : Integer := G (F); 
> > >	    type T is tagged null record; 
> > >	end Stt;
> >
> > As written compilers will probably replace the call to G to 
> > initialize 
> > I  with a raise of Program_Error.
> 
> Maybe, maybe not, but that's irrelevant.  The rules of the language should
> not depend on a compiler performing (or not performing) an optimization.

There were cases like that in Ada 83.  I think X.all was legal, where X is of
an incomplete type, and the compiler had to deduce that X must be null to
avoid tripping over itself.  Or something like that.  Anyway, we (tried to)
eliminate such cases.

General principle: it's silly to require a compiler to deduce some fact, and
respond by generating code to raise an exception.  If we're going to require
such a deduction, the response should be a (legality) error message.  And it's
our duty to write down what needs to be deduced, rather than leaving it
implicit.

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

From: Tucker Taft
Date: Thursday, August 3, 2006 10:42 AM

> The call to G is dispatching, so we better know the location of the tag
> for type T.  But I am not sure if 13.14(14) helps, because I have always
> interpreted "subtype of its profile" to mean the subtypes of the
> parameters or result (access T or access T'Class here) not any random
> subtype that happens to appear in the profile (like T here).  

The "subtypes of a profile" are defined in 6.1(26-29) to include
the designated subtype of an access parameter or result.
So calling a subprogram with an access parameter actually freezes
the designated subtype as well (which is a bit of a surprise
to me -- not clear how this relates to T.A. types, or limited
with's for that matter).

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

From: Pascal Leroy
Date: Friday, August 4, 2006  2:12 AM

Ah, good point, I missed that.  Yes, it's a bit surprising, but I guess it
helps a lot with dispatching.

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

From: Randy Brukardt
Date: Friday, August 4, 2006  2:08 PM

Absolutely. It's surely necessary that any type that can be dispatched upon
is frozen (else we don't necessarily know where the tag is), and this rule
ensures that. We have rules that make dispatching calls illegal if we can't
locate the tag (T.A. types, for instance).

I think a more interesting question is how this relates to non-dispatching
calls (i.e. classwide calls), where we explicitly allowed
access-to-incomplete. (This means that you don't have to have junk withs for
packages that were limited withed just to see the full type so you can make
a call that doesn't depend on the full type anyway.) OTOH, the interesting
case is types declared elsewhere (limited with), and such types are presumed
frozen already; if such calls are illegal for T.A. types, it's not a huge
deal.

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


Questions? Ask the ACAA Technical Agent