CVS difference for ais/ai-50217.txt

Differences between 1.5 and version 1.6
Log of other versions for file ais/ai-50217.txt

--- ais/ai-50217.txt	2003/08/01 01:40:09	1.5
+++ ais/ai-50217.txt	2003/08/08 01:44:11	1.6
@@ -3441,7 +3441,7 @@
 -----------------
 Thoughts on the implementation of "limited with" in AdaMagic
 
-          $Revision: 1.5 $ $Date: 2003/08/01 01:40:09 $
+          $Revision: 1.6 $ $Date: 2003/08/08 01:44:11 $
 
 The "limited with" clause makes a "limited view"
 of a package visible in the compilation unit
@@ -5250,7 +5250,7 @@
 -----------------
 Thoughts on the implementation of "limited with" in AdaMagic
 
-          $Revision: 1.5 $ $Date: 2003/08/01 01:40:09 $
+          $Revision: 1.6 $ $Date: 2003/08/08 01:44:11 $
 
 The "limited with" clause makes a "limited view"
 of a package visible in the compilation unit
@@ -5757,4 +5757,3420 @@
 :-) :-)
 
 **************************************************************
+
+From: Randy Brukardt
+Sent: Saturday, March 22, 2003 12:36 AM
+
+
+This example shows two ways that I would use alternative #6 of AI-217
+in the Claw Builder. See the similar write-up on alternative #5 for details
+about the Builder and why it is important to be able to use this facility in
+it.
+
+[Editor's note: Here are those details.]
+
+The Claw Builder is a real, existing program which could use this facility.
+The problem is that some objects need references to other types of objects,
+and these needs are circular. For instance, (some) types of window objects
+include menu objects. And some types of menu objects include actions that
+open a window.
+
+The current Claw Builder solves this problem by using names rather than
+access objects to connect the objects in some cases. This is usually done
+only where necessary to break circularities. For instance, menu objects name
+the windows they are to open, rather than linking to them. Using names
+causes several problems:
+   -- Accesses to the linked object is much slower, as they have to be
+      looked up by name before use;
+   -- If the user renames the linked object, we have to walk the entire
+      project to insure any names are updated;
+   -- If the user copies the linked object and then renames the copy (the
+      required behavior), we have to be careful NOT to walk the project
+      and update names -- harming code reuse.
+   -- We can't have overloaded names (not a problem for windows, but can
+      happen in other cases).
+
+A root window object is an abstract object with a fairly large set of
+operations. Each concrete object has to provide implementations for many of
+these operations (some it can inherit). All of these operations are
+dispatching. Typically, a user of the operation would apply it to a list of
+windows using an iterator generic, with the operation dispatching to the
+correct implementation. For the purposes of this discussion, we'll look at
+just a few: Show, Hide, Display_Name.
+
+The existing package looks something like:
+
+   with CBuild_Menu;
+   package CBuild_Root is
+      type Root_Window_Type is abstract new
+	    Ada.Finalization.Limited_Controlled with private;
+      type Any_Window_Access_Type is access all Root_Window_Type'Class;
+
+      procedure Show (Window : in out Root_Window_Type) is abstract;
+      procedure Hide (Window : in out Root_Window_Type) is abstract;
+      function Display_Name (Window : in Root_Window_Type)
+          return String is abstract;
+      ...
+   private
+      type Root_Window_Type is abstract new
+	    Ada.Finalization.Limited_Controlled with record
+          ... CBuild_Menu.Something ...
+      end record;
+   end CBuild_Root;
+
+The menu package looks something like (greatly simplified):
+
+  with CBuild_Id_Type;
+  package CBuild_Menu is
+    type Menu_Item is record
+       Name : String (1..20);
+       Action : Action_Type;
+       Dialog : CBuild_Id_Type; -- The name of a dialog window.
+           -- If Action=Open_Dialog.
+    end record;
+    procedure Simulate_Action (Item : in Menu_Item);
+  end CBuild_Menu;
+
+  with CBuild_Root, CBuild_Lists;
+  package body CBuild_Menu is
+    procedure Simulate_Action (Item : in Menu_Item) is
+    begin
+       if Item.Action = No_Action then
+           null;
+       elsif Item.Action = Open_Dialog then
+           CBuild_Root.Show (
+                 CBuild_Lists.Lookup(Item.Dialog,
+                     CBuild_Data.Top_Level_Window_List));
+       ... -- Other actions.
+       end if;
+    end Simulate_Action;
+  end CBuild_Menu;
+
+[End details copied from alternative #5.]
+
+In order to directly use a Any_Window_Access_Type instead of the name in
+CBuild_Menu, we would need restructure the CBuild_Root package. We'd need to
+construct an abstract of this package for use in circular definitions. This
+is necessary to have a single access type, which avoids the need to use a
+conversion on nearly every use. Using alternative #7 (and assuming that
+AI-326 is approved), this could look like:
+
+   limited with CBuild_Root;
+   package CBuild_Root_Abstract is
+      type Any_Window_Access_Type is access all
+          CBuild_Root.Root_Window_Type'Class;
+   end CBuild_Root_Abstract;
+
+This abstract would be used only when you need to declare instances (usually
+components) of the type in locations where the reference would be circular.
+
+Since we don't want an extra access type, the real package would be
+modified to:
+
+   with CBuild_Root_Abstract;
+   with CBuild_Menu;
+   package CBuild_Root is
+      type Root_Window_Type is abstract new
+	    Ada.Finalization.Limited_Controlled with private;
+      subtype Any_Window_Access_Type is
+CBuild_Root_Abstract.Any_Window_Access_Type;
+
+      procedure Show (Window : in out Root_Window_Type) is abstract;
+      procedure Hide (Window : in out Root_Window_Type) is abstract;
+      function Display_Name (Window : in Root_Window_Type)
+          return String is abstract;
+      ...
+   private
+      type Root_Window_Type is abstract new
+	    Ada.Finalization.Limited_Controlled with record
+          ... CBuild_Menu.Something ...
+      end record;
+   end CBuild_Root;
+
+The client package (in this case, for menus) would look something like:
+
+  with CBuild_Root_Abstract;
+  package CBuild_Menu is
+    type Menu_Item is record
+       Name : String (1..20);
+       Action : Action_Type;
+       Dialog : CBuild_Root_Abstract.Any_Window_Access_Type;
+           -- If Action=Open_Dialog.
+    end record;
+    procedure Simulate_Action (Item : in Menu_Item);
+  end CBuild_Menu;
+
+  with CBuild_Root;
+  package body CBuild_Menu is
+    procedure Simulate_Action (Item : in Menu_Item) is
+    begin
+       if Item.Action = No_Action then
+           null;
+       elsif Item.Action = Open_Dialog then
+           CBuild_Root.Show (Item.Dialog.all);
+       ... -- Other actions.
+       end if;
+    end Simulate_Action;
+  end CBuild_Menu;
+
+As I've said twice before, I don't much like this solution, because it's not
+clear when to use the abstract package, and when to use the main package. It
+would be preferable to keep an understandable separation between them.
+
+One way to do this is create a "client" package and a "creator" package. The
+"client" package  would be used by ordinary client packages of the
+abstraction. The "creator" package would be used only by packages that need
+to create new extensions of the type or create objects of the type. The
+"creator" package would, of course, be similar to the existing package. The
+"client" package would provide enough operations that regular clients could
+use it only.
+
+Since the "client" package would be used most frequently, I've given it the
+existing name.
+
+   limited with CBuild_Root_Definition;
+   package CBuild_Root is
+      type Any_Window_Access_Type is access all
+          CBuild_Root_Definition.Root_Window_Type'Class;
+
+      procedure Show (Window : in out
+          CBuild_Root_Definition.Root_Window_Type'Class);
+      procedure Hide (Window : in out
+          CBuild_Root_Definition.Root_Window_Type'Class);
+      function Display_Name (Window : in
+          CBuild_Root_Definition.Root_Window_Type'Class)
+          return String;
+      ...
+   end CBuild_Root;
+
+One annoyance here is the need to give the fully expanded name of the
+incomplete type, over and over. That's because use clauses are prohibited on
+the limited withed package. But I'll live. :-)
+
+The "creator" package would be as in the previous example (except for the
+name):
+
+   with CBuild_Root;
+   with CBuild_Menu;
+   package CBuild_Root_Definition is
+      type Root_Window_Type is abstract new
+	    Ada.Finalization.Limited_Controlled with private;
+      subtype Any_Window_Access_Type is CBuild_Root.Any_Window_Access_Type;
+
+      procedure Show (Window : in out Root_Window_Type) is abstract;
+      procedure Hide (Window : in out Root_Window_Type) is abstract;
+      function Display_Name (Window : in Root_Window_Type)
+          return String is abstract;
+      ...
+   private
+      type Root_Window_Type is abstract new
+	    Ada.Finalization.Limited_Controlled with record
+          ... CBuild_Menu.Something ...
+      end record;
+   end CBuild_Root_Definition;
+
+The body of CBuild_Root would need visibility on the completing type so that
+it
+could implement the procedures:
+
+   with CBuild_Root_Definition;
+   package body CBuild_Root is
+      procedure Show (Window : in out
+          CBuild_Root_Definition.Root_Window_Type'Class) is
+      begin
+          CBuild_Root_Definition.Show (Window);
+      end Show;
+      procedure Hide (Window : in out
+          CBuild_Root_Definition.Root_Window_Type'Class) is
+      begin
+          CBuild_Root_Definition.Hide (Window);
+      end Hide;
+      function Display_Name (Window : in
+          CBuild_Root_Definition.Root_Window_Type'Class)
+          return String is
+      begin
+          return CBuild_Root_Definition.Display_Name (Window);
+      end Display_Name;
+      ...
+   end CBuild_Root;
+
+With this structure, the clients with CBuild_Root, and the concrete object
+packages with (or are children of) CBuild_Root_Definition. The two packages
+have clearly defined roles.
+
+With these packages, the use of the types in the menu package is the same
+for all three alternatives:
+
+  with CBuild_Root;
+  package CBuild_Menu is
+    type Menu_Item is record
+       Name : String (1..20);
+       Action : Action_Type;
+       Dialog : CBuild_Root.Any_Window_Access_Type;
+            -- If Action=Open_Dialog.
+    end record;
+    procedure Simulate_Action (Item : in Menu_Item);
+  end CBuild_Menu;
+
+  package body CBuild_Menu is
+    procedure Simulate_Action (Item : in Menu_Item) is
+    begin
+       if Item.Action = No_Action then
+           null;
+       elsif Item.Action = Open_Dialog then
+           CBuild_Root.Show (Item.Dialog.all);
+       ... -- Other actions.
+       end if;
+    end Simulate_Action;
+  end CBuild_Menu;
+
+---
+
+Of course, the best way to avoid the issue of deciding when to use one of
+the two packages is to avoid having the second one in the first place. The
+primary reason we need this package is because of access type proliferation
+problems. If the solution in AI-230 is adopted, we don't have that problem.
+In that case, we can put the stub directly in the menus package.
+
+In that case, the CBuild_Root package need not be modified at all:
+
+   with CBuild_Menu;
+   package CBuild_Root is
+      type Root_Window_Type is abstract new
+	    Ada.Finalization.Limited_Controlled with private;
+      type Any_Window_Access_Type is access all Root_Window_Type'Class;
+
+      procedure Show (Window : in out Root_Window_Type) is abstract;
+      procedure Hide (Window : in out Root_Window_Type) is abstract;
+      function Display_Name (Window : in Root_Window_Type)
+          return String is abstract;
+      ...
+   private
+      type Root_Window_Type is abstract new
+	    Ada.Finalization.Limited_Controlled with record
+          ... CBuild_Menu.Something ...
+      end record;
+   end CBuild_Root;
+
+Then, the menu package would declare the stub and an anonymous access type:
+
+  limited with CBuild_Root;
+  package CBuild_Menu is
+    type Menu_Item is record
+       Name : String (1..20);
+       Action : Action_Type;
+       Dialog : access CBuild_Root.Root_Window_Type'Class;
+           -- If Action=Open_Dialog.
+    end record;
+    procedure Simulate_Action (Item : in Menu_Item);
+  end CBuild_Menu;
+
+  with CBuild_Root;
+  package body CBuild_Menu is
+    procedure Simulate_Action (Item : in Menu_Item) is
+    begin
+       if Item.Action = No_Action then
+           null;
+       elsif Item.Action = Open_Dialog then
+           CBuild_Root.Show (Item.Dialog.all);
+       ... -- Other actions.
+       end if;
+    end Simulate_Action;
+  end CBuild_Menu;
+
+This solution clearly perturbs the existing program the least, so it is
+preferred if it is available.
+
+It's interesting to note that alternatives #5 and #6 look essentially the
+same on this program. The structure of the program is the same, presuming
+the same assumptions about the language features employed. The advantage of
+alternative #5 is to be able to give a different, visible name to the stub
+(which simplifies the rules and probably the implementation, but which I
+didn't take advantage of in this moderately sized example). The advantage of
+#6 is not to have to declare the stub at all.
+
+Alternative #7 perturbs the structure of the program further, and can't
+really handle the last example at all. That makes it a distant third in my
+view. Alternative #6 probably has the edge on ease of use, but I'd like to
+see a worked-out version whose visibility/availability rules really work
+before I could even give it a partial endorsement. (And it always will be
+much more expensive to implement.)
+
+That concludes my look at implementing the Claw Builder using these
+alternatives. One more piece of homework done. Yeah!!!
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Friday, March 21, 2003  8:31 AM
+
+> That means, in fact, that visibility IS the right model here, as long as
+> it is clear that it is the visibility of the original completing
+> declaration that we are talking about, and not the visibility of some subtype
+> name that happens to be declared somewhere else.
+
+The more I read chapter 8 (and the mail messages that Tuck and you
+wrote) the more confused I am.
+
+Consider the example:
+
+    package P is
+        type T is new Boolean;
+    end P;
+
+    with P;
+    package Q is
+    end Q;
+
+    limited with P;
+    with Q;
+    package R is
+        X : P.T; -- Legal?
+    end R;
+
+The question is: is the limited (or incomplete if you prefer) view of
+P.T hidden from all visibility in R?  If I read Tuck's proposed change
+to 8.3(19) it seems that the answer is a resounding Yes.
+
+The reason is that 8.3(14) says that "a declaration is visible within
+its scope, except when hidden from all visibility."  R is clearly part
+of the scope of P.T, because Q is a semantic dependent of P and R is a
+semantic dependent of Q.  And none of the "hidden from all visibility"
+rules apply to P.T here (see 8.3(15-20)).  So the completion of P.T is
+visible in R, and the incomplete view of P.T is hidden from all
+visibility.
+
+None of this is new, but in Ada 95 (where you don't have "limited with")
+P is hidden from all visibility within R because of 8.3(20), so even
+though P.T is visible in R, it cannot be named (wonderful language!).
+However the "limited with" clause clearly makes (the limited view of) P
+visible in R, and so P.T can be named, and the declaration of X is
+legal.
+
+But of course there is an awful ripple effect here, because removing the
+"with P" in Q causes R to become illegal.  Yuck.
+
+In essence, I guess I am saying that visibility has the same
+transitivity effect as scope as far as I can tell.
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Friday, March 21, 2003  9:28 AM
+
+> The question is: is the limited (or incomplete if you prefer) view of
+> P.T hidden from all visibility in R?  If I read Tuck's proposed change
+> to 8.3(19) it seems that the answer is a resounding Yes.
+
+That was certainly not my intent.  I have suggested that 8.3(19)
+be changed so that the hidden-from-all-visibility only happens
+where the completion is *visible* as opposed to throughout
+the scope of the completion.  In the above, the completion is
+*not* visible inside R, so the incomplete declaration is
+not hidden.  But as I read on...
+
+> The reason is that 8.3(14) says that "a declaration is visible within
+> its scope, except when hidden from all visibility."  R is clearly part
+> of the scope of P.T, because Q is a semantic dependent of P and R is a
+> semantic dependent of Q.  And none of the "hidden from all visibility"
+> rules apply to P.T here (see 8.3(15-20)).  So the completion of P.T is
+> visible in R, and the incomplete view of P.T is hidden from all
+> visibility.
+
+Hmmmm....  I see your point.  I was presuming that if there is
+no way to name the enclosing package, then all the declarations
+in the visible part of the package are similarly hidden from
+all visibility.  The RM doesn't back up that view.  It looks
+like in addition to changing 8.3(19) we would have to also
+change 8.3(14) roughly as follows:
+
+  A declaration is visible within its immediate scope except where hidden
+  from all visibility.  A declaration that occurs immediately within the
+  visible part of an enclosing visible declaration, or that is a public
+  child of a visible declaration, is visible except where
+  hidden from all visibility.  A declaration is hidden from all visibility
+  as follows:
+
+
+>
+> None of this is new, but in Ada 95 (where you don't have "limited with")
+> P is hidden from all visibility within R because of 8.3(20), so even
+> though P.T is visible in R, it cannot be named (wonderful language!).
+> However the "limited with" clause clearly makes (the limited view of) P
+> visible in R, and so P.T can be named, and the declaration of X is
+> legal.
+>
+> But of course there is an awful ripple effect here, because removing the
+> "with P" in Q causes R to become illegal.  Yuck.
+>
+> In essence, I guess I am saying that visibility has the same
+> transitivity effect as scope as far as I can tell.
+
+Good point.  As suggested above, 8.3(14) would also have to be changed
+to make the change to 8.3(19) useful.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Friday, March 21, 2003  3:28 PM
+
+> Hmmmm....  I see your point.  I was presuming that if there is
+> no way to name the enclosing package, then all the declarations
+> in the visible part of the package are similarly hidden from
+> all visibility.  The RM doesn't back up that view.  It looks
+> like in addition to changing 8.3(19) we would have to also
+> change 8.3(14) roughly as follows:
+>
+> A declaration is visible within its immediate scope except
+> where hidden from all visibility.  A declaration that occurs immediately
+> within the visible part of an enclosing visible declaration, or that
+> is a public child of a visible declaration, is visible except where
+> hidden from all visibility.  A declaration is hidden from
+> all visibility as follows:
+
+The second sentence doesn't seem to solve the problem.  It says in essence
+"A declaration ... is visible except where hidden from all visibility".
+That's not saying where it's visible (I presume that you don't want to say
+that it's visible to the entire universe, even outside its scope).  I would
+have expected a qualification like "is visible <at some places> except where
+hidden from all visibility."
+
+I'm not sure what to put in the <>, though.  Maybe "is visible at the places
+where the enclosing declaration or parent unit is visible, except ..."?
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Friday, March 21, 2003  4:02 PM
+
+We can just fall back on "scope" I think.
+I.e.:
+   Outside its immediate scope, but within its (extended) scope, a declaration that is not
+   hidden from all visibility is visible if the declaration of the
+   immediately enclosing declarative region, or a renaming thereof, is visible.
+
+But this may be overkill, if we adopt one of the more restrictive versions
+of 8.3(19) that I have suggested.  E.g., if we say that:
+
+   a declaration is hidden from all visibility within the immediate scope
+   of its completion, and within the extended scope of the completion where
+   the declaration of the (completion's) enclosing library unit, or a library
+   unit renaming thereof, is visible.
+
+Or something like that...
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Monday, March 24, 2003  3:31 PM
+
+BTW, Pascal, how is AI-217-06 coming?
+
+I've just been thinking that the 'two views' problem is impossible to avoid
+without serious ripple effects. If that's true, of course, 'limited with' is
+dead in the water, because it will be even harder to implement than
+previously thought (I'd say impossible, but of course it's always possible
+to implement anything self-consistent.)
+
+The problem is that you have a 'view' of a package in your symboltable any
+time the package is in the semantic closure. Thus, any rule that attempts to
+avoid 'two views' issue is going to cause ripple effects.
+
+For example:
+
+      package P is
+          type Root is abstract tagged ...;
+      end P;
+
+      with P;
+      package Q is
+          type Win is new Root with ...
+      end Q;
+
+      with Q;
+      package R is
+          Main : Q.Win;
+      end R;
+
+      limited with P;
+      with Q, R;
+      package S is
+          type Any_Root is access all P.Root; -- Legal?
+          Child : Q.Win := R.Main;
+      end S;
+
+Clearly, we have a full view of P in our semantic closure, so all of the
+information about type Root will be loaded (but not visible). That's clearly
+necessary so we can handle the initialization of Child. (In Janus/Ada, the
+entire symboltable for the package is loaded in this case, but I suppose one
+could arrange to load only a partial view - but that view necessarily has
+quite a bit more information that the 'limited view' does.)
+
+The rules that we've discussed for fixing this problem is that the limited
+with would be either illegal or ignored in some case. In order to avoid
+having two views, the rule clearly has to be effective any time the package
+P is in the semantic closure (as in this example).
+
+In that case, either the 'limited with P' is illegal (but that seems
+confusing to the user, as there is no sign of any P in package S), or the
+'limited with P' is ignored, meaning the 'P.Root' is illegal, since there is
+no P visible (which is even more confusing to the user).
+
+Moreover, if maintenance changes Q to not depend on P, then of course S
+becomes legal: a classic ripple effect. Of course, the ripple effect is bad
+if it occurs in the other direction. Presume that a fielded system was a
+package Q that doesn't depend on P. S is legal. Then, if maintenance adds a
+'with P' to package Q, S becomes illegal. (And S would be illegal even if
+Child wasn't declared and package Q wasn't withed by S.)
+
+Ripple effects like this can't be tolerated. Thus, it appears to me that we
+cannot legislate away the 'two views' problem. That makes the implementation
+cost of this proposal far more than we thought in Padua (and that was higher
+than the other proposals to begin with).
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Wednesday, March 26, 2003  8:49 AM
+
+> I've just been thinking that the 'two views' problem is impossible to
+> avoid without serious ripple effects. If that's true, of course, 'limited
+> with' is dead in the water...
+
+The first sentence may actually be true, but I fail to see the logical
+connection with the second sentence.  Certainly the "type C.T" proposal
+has exactly the same problem.  The type stubs proposal is a bit
+different because the stub and the completion have different names, but
+you still have to have both views in your hand and decide which one to
+use.  Here is an example:
+
+        limited with P;
+        package P_Stub is
+            type Root is tagged separate of P.Root;
+        end P_Stub;
+
+        with P_Stub;
+        package P is
+            type Root is tagged ...;
+        end P;
+
+        with P;
+        package Q is
+            type Arr is array (1..10) of P.Root;
+        end Q;
+
+        with Q;
+        package R is
+            Pain : Q.Arr;
+        end R;
+
+        with P_Stub;
+        with Q, R;
+        package S is
+            X : P_Stub.Root; -- Illegal, completion not available.
+            Y : Boolean := Q.Arr (1) = Q.Arr (2); -- Legal
+        end S;
+
+So on each construct you have to be extra-cautious to determine if you
+are allowed to peek at the completion or if you must stop at the stub.
+(There is a similar problem in the current language with private types.)
+
+>       package P is
+>           type Root is abstract tagged ...;
+>       end P;
+>
+>       with P;
+>       package Q is
+>           type Win is new Q.Root with ...
+>       end Q;
+>
+>       with Q;
+>       package R is
+>           Main : Q.Win;
+>       end R;
+>
+>       limited with P;
+>       with Q, R;
+>       package S is
+>           type Any_Root is access all P.Root; -- Legal?
+>           Child : Q.Win := R.Main;
+>       end S;
+
+I have actually played with a different mechanism to solve this
+conundrum.  I am very far from having RM words at this point, but the
+idea would be that P.Root would become incomplete again in the scope of
+the "limited with P".  This means that simply by looking at the context
+clause (and the ones you inherits) you could decide which view of P
+needs to be made available.  There would not be ripple effects, because
+it would all be based on the scope of with clauses.
+
+With this mechanism, the declaration of Any_Root would of course be
+legal, but the declaration of Child would not, because Q.Win would be a
+type with an incomplete component.  This might seem a bit odd, but it's
+probably OK for the user: if you want to declare a variable of type
+Q.Win, then surely you can write a "with P" so the "limited with P"
+appears pointless.
+
+I realize that this is all half-baked...
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, March 26, 2003  9:46 AM
+
+> I realize that this is all half-baked...
+
+You should also include in every example a visible
+non-library-unit renaming of P, just to be sure you
+have a good answer for that.
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, March 26, 2003  1:29 PM
+
+> The first sentence may actually be true, but I fail to see the logical
+> connection with the second sentence.  Certainly the "type C.T" proposal
+> has exactly the same problem.
+
+type C.T does not meet the SigAda criteria IMO, and I'm thinking about it as
+little as possible. I'd motion to kill it, but I'll have to wait until June
+to do that.
+
+...
+> So on each construct you have to be extra-cautious to determine if you
+> are allowed to peek at the completion or if you must stop at the stub.
+> (There is a similar problem in the current language with private types.)
+
+Of course, every Ada compiler has to be prepared to handle two views of the
+same type. I'm concerned about two views of the same (original) fully
+expanded name, and especially two views of the CONTENTS of the same name.
+
+In Janus/Ada, we handle visibility of names by two mechanisms: standard
+scoping, and a visibility bit. The second was added to handle things that
+are invisible but still are in scope: units in the semantic closure,
+inherited private record components, etc. Package renames are implemented by
+a pointer to the original package node.
+
+But neither of these allow a name to be both visible by one path and
+invisible by another path. If we have a path that allows us access to all
+the package contents, then any path that will get us to the package node is
+going to have access to all the package contents.
+
+Similarly, the limited with proposal doesn't bring discriminants in. These
+of course are part of the contents of the type. If the type has
+discriminants, we don't have a way to prevent accessing them (or knowing
+about their existence) if some other view supposedly doesn't have them.
+(Some such uses would be illegal for other reasons, but this certainly comes
+up if we allow Tucker's deferencing rules; but I'd expect that it would come
+up in other ways as well.)
+
+> I have actually played with a different mechanism to solve this
+> conundrum.  I am very far from having RM words at this point, but the
+> idea would be that P.Root would become incomplete again in the scope of
+> the "limited with P".  This means that simply by looking at the context
+> clause (and the ones you inherits) you could decide which view of P
+> needs to be made available.  There would not be ripple effects, because
+> it would all be based on the scope of with clauses.
+
+There would still be ripple effects in children, but since those happen in
+the existing language, presumably we can ignore that. (Removing a with from
+the parent can make children illegal).
+
+> With this mechanism, the declaration of Any_Root would of course be
+> legal, but the declaration of Child would not, because Q.Win would be a
+> type with an incomplete component.  This might seem a bit odd, but it's
+> probably OK for the user: if you want to declare a variable of type
+> Q.Win, then surely you can write a "with P" so the "limited with P"
+> appears pointless.
+
+Well, that's counter to the principle of least visibility (that is, only use
+the least visibility that you have to get the job done). That effectively
+makes limited with look like a hack, because you can only use it in very
+limited circumstances, and it possibly would break other, unrelated code. Of
+course, it IS a hack; I'm certain that an elegant solution to this problem
+doesn't exist.
+
+In any case, this sounds like no real proposal is going to be on the table
+soon, so I'm going to give this whole subject lower priority for now.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Thursday, March 27, 2003  4:54 AM
+
+Well, I admit that it may be a bit surprising to the user, but not more
+than ripple effects or that an unused package renaming in an auxiliary
+unit affecting the visibility.  I contend that it's not going to happen
+often in practice.  And it's probably not worse (and less frequent) than
+name clashes in use clauses or reemergence in generics, which when you
+think of it are odd too (only, we've got used to them).
+
+>       package P is
+>           type Root is abstract tagged ...;
+>       end P;
+>
+>       with P;
+>       package Q is
+>           type Win is new Root with ...
+>       end Q;
+>
+>       with Q;
+>       package R is
+>           Main : Q.Win;
+>       end R;
+>
+>       limited with P;
+>       with Q, R;
+>       package S is
+>           type Any_Root is access all P.Root; -- Legal?
+>           Child : Q.Win := R.Main;
+>       end S;
+
+Look at your original example again.  Why the hell do you write "limited
+with P" in S?  I can see two reasons:
+
+1 - S and P are part of a cycle.  Then P will need to have a "limited
+with S" and I'm not sure why you wouldn't write "with P" in S.  At any
+rate, this looks like cheesy OO design to me.  You'll have to give a
+more convincing example to demonstrate that there is a usability problem
+here.
+
+2 - You want to document/ensure that S only uses the limited view of P.
+Then I am going to argue that my model is exactly what you want, because
+it effectively hides the full view of P.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Thursday, March 27, 2003  5:18 AM
+
+> I would encourage
+> Pascal to produce something soon, even if it lacks
+> detailed wording, so long as it captures his intent
+> in a way that others can review it.
+
+OK, you'll find below an attempt at capturing my ideas on visibility in
+RM wording.  I'm pretty sure there will be adjustments needed (I never
+seem to get wording right) but it should give enough detail for others
+(in particular, Tuck and Randy) to review.
+
+This approach is supposed to:
+
+1 - Solve the two-view problem: at the end of the context clause the
+compiler knows which view it must grab.
+2 - Solve the ripple effect problem: it's all phrased in terms of the
+scope of with clauses, so distant changes in visibility/renamings don't
+affect the legality of a unit.
+
+Assuming that these rules work, I would be strongly in favor of using
+them for the "type C.T" proposal, as it has the same problems.  The
+current rules of AI 217-07 are nearly impossible to implement for an
+incremental compiler.  (Well, I would be strongly in favor of killing
+AI 217-07 altogether, but that's a different discussion.)
+
+Let me look specifically at two examples to explain the consequences of
+the rules.  First, an example from the minutes of the Padua meeting:
+
+    package Q is
+        type T is ...;
+        Z : T;
+    end Q;
+
+    limited with Q;
+    package P is
+        type Acc is access Q.T;
+        X : Acc;
+    end P;
+
+    with Q;
+    package A is
+        package MyQ renames Q;
+    end A;
+
+    limited with Q;
+    with P; with A;
+    package R is
+        P.X.all; -- Illegal, causes freezing of the incomplete type Q.T.
+        A.MyQ.Z -- Illegal, full view of Q hidden from all visibility.
+        Q.Z -- Illegal, full view of Q hidden from all visibility.
+    end R;
+
+And then the example that Randy circulated recently:
+
+      package P is
+          type Root is abstract tagged ...;
+      end P;
+
+      with P;
+      package Q is
+          type Win is new Root with ...
+      end Q;
+
+      with Q;
+      package R is
+          Main : Q.Win;
+      end R;
+
+      limited with P;
+      with Q, R;
+      package S is
+          type Any_Root is access all P.Root; -- Legal.
+          Child : Q.Win := R.Main; -- Illegal, freezing P.Root.
+      end S;
+
+The rules will be found below, each paragraph of wording following by a
+[bracketed] paragraph explaining the purpose of the rule.
+
+--
+
+- Add after 10.1.2(5):
+
+A with_clause is *more nested than* another with_clause if they are both
+part of the same context_clause, or if the scope of the first
+with_clause is entirely included in the scope of the second with_clause.
+
+[We need to define the nesting of with_clauses to phrase a number of
+rules that describe the interaction between nonlimited_ and
+limited_with_clauses appearing on different units. Note that a
+with_clause is more nested than itself (not that it matters much, but it
+make some of the wording simpler).]
+
+- Replace 10.1.2(6) by:
+
+A library_item is *explicitly mentioned* in a with_clause if it is
+denoted by a library_unit_name in the with_clause. A library_item is
+mentioned in a nonlimited_with_clause if it is explicitly mentioned or
+if it is denoted by a prefix in the with_clause. A library_item is
+mentioned in a limited_with_clause if it is explicitly mentioned or if
+it is denoted by a prefix in the with_clause, and that with_clause is
+not more nested than a nonlimited_with_clause that mentions the same
+library_item.
+
+[For nonlimited_with_clauses, this doesn't change the current RM. For
+limited_with_clause, it says that if for instance the specification of Q
+has a "with P" and the body of Q has a "limited with P.R.S" then P is
+not mentioned in the limited_with_clause. So the limited_with_clause has
+no effect for P; in particular it doesn't revert to the limited view of
+P. On the other hand, it makes the limited views of P.R and P.R.S
+visible. This is mostly a methodological restriction, as we have
+(pathological) cases where the limited view hides the full view.
+However, we want to make such cases infrequent, in part to avoid
+confusing users, and in part to account for the fact that the checks
+associated with "reverting" to a limited view may be a bit costly.]
+
+- Add after 10.1.2(8):
+
+A limited_with_clause which explicitly mentions a library_item shall not
+be more nested than a nonlimited_with_clause which mentions the same
+library_item.
+
+[Thus, if for instance the specification of Q has a "with P.R", it shall
+not have a "limited with P" or a "limited P.R". The same applies to the
+body of Q, its subunits, etc. On the other hand, a "limited with P.R.S"
+is fine. Again this is to avoid reverting to the limited view as much as
+possible.]
+
+- Add after 8.3(20):
+
+The full view of a library_item is hidden from all visibility within the
+scope of a limited_with_clause that mentions it. The limited view of a
+library_item is hidden from all visibility within the declarative region
+of the library_item, and within the scope of a nonlimited_with_clause
+that mentions it.
+
+[The first sentence is the rule that prevents ripple effects and the
+two-view problem. If you are is the scope of a "limited with P", the
+full view of P is hidden from all visibility, even if P would otherwise
+be visible indirectly (e.g. by a renaming in an auxiliary package). So
+the limited_with_clause effectively reverts to the limited view of P,
+and the types it declares are incomplete, and therefore subject to the
+limitations described in 3.10.1. From an implementation standpoint, it
+means that compilers can decide early (i.e., after looking at the
+context_clauses of a unit and of its ancestry) what view of P needs to
+be made available, and they never have to juggle with both views. Note
+that I expect this rule to kick in only in rather pathological
+situations: if you are at a place where the full view of P is visible,
+it is unclear why you would want to write "limited with P", except
+perhaps to document the fact that at this point you only use the limited
+view.]
+
+- Replace 3.11.1(8) by:
+
+A type is completely defined at a place that is after its full type
+definition (if it has one) and after all of its subcomponent types are
+completely defined. Furthermore, if the type is declared within the
+visible part of a library_item, it is *not* completely defined within
+the scope of a limited_with_clause that mentions the enclosing
+library_item. A construct that causes freezing of a type shall occur at
+a place where the type is completely defined (see 13.14 and 7.3).
+
+[Within the scope of a "limited with P", not only is P.T an incomplete
+type, but any type that has a part of type P.T is incompletely defined.
+Such types could exist because they would be declared in auxiliary units
+where the full view of P is visible. This rule makes it possible to
+piggyback on the freezing rules: within the scope of a "limited with P",
+any construct that would cause freezing of P.T is illegal. Surely
+compilers already have mechanisms to implement the freezing rules, and
+for instance on every object_declaration they have to verify that the
+type doesn't have incompletely defined subcomponents. It is hoped that
+it would be relatively straightforward to modify these mechanisms to
+implement this rule. One difference though is that currently compilers
+never have to look at the parent part because 13.14(7) ensures that it
+is frozen. To implement the new rule, the parent part would have to be
+inspected. If performance is a concern, this part of the check could
+only be performed in the scope of a limited_with_clause.]
+
+- Replace 13.14(17) by:
+
+A construct that causes freezing of a type shall occur at a place
+where the type is completely defined.
+
+[A simple copy of the last sentence of 3.11.1(8). This rule is redundant
+anyway. Note that within the scope of a "limited with P" the type P.T is
+incompletely defined, but it is still frozen as explained in the second
+sentence of 13.14(2) (I don't want to mess with the freezing rules).
+What we have here is a construct that causes freezing occurring after
+the freezing point, and such a construct is illegal if the type has
+reverted to "incompletely defined".]
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Thursday, March 27, 2003  5:49 AM
+
+Looks good to me!  Thanks for making the effort
+to provide this sooner rather than later.
+I'll see if I can figure out how an approach like
+this could apply to the incomplete child type
+proposal, and I presume Randy will do the same
+for the type stub proposal.
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Thursday, March 27, 2003  9:11 AM
+
+I have interspersed some detailed comments with your
+proposed wording.  But first, to summarize...
+
+My major comment is that we should restrict ourselves to
+talking about what is in the limited view of a package,
+namely it contains limited views of nested packages, and
+incomplete type declarations.  It seems unnecessary to go and
+render incomplete other uses of a type declared in
+the package, presuming those uses appeared in
+places where a full view of the package existed
+(e.g. objects of the type, or subtypes of the
+type, or types derived from subtypes of the type, or ...).
+
+This is mostly to simplify implementations, though I
+think it also reduces the number of wording changes.  Right
+now, the freezing rules never need to be of concern
+when handling statements.  They only apply to expressions
+and names that appear in declarations.  With the change you
+are proposing, freezing checks have to be performed
+in all statements as well, and that seems like overkill.
+
+I think the very *good* part about your proposal is
+that it implies that any renaming of a package, when
+within the limited view of the package, is considered
+limited.  I think that is the big improvement over
+earlier proposals, and is probably the most intuitive
+for the user.
+
+If we focus just on the limited package view and what it contains,
+and not worry about visible entities that are somehow
+based on information gleaned from a full view of the package,
+then that keeps the implementation effort focused
+on package names, and whether they denote a full view
+or an incomplete view.  That is a nice place to focus,
+because there is already work needed when dealing with
+package names and renames, to be sure to include children,
+decide whether the private part is visible, etc.  This might
+be a relatively small increment on that.  I fear if you
+start burdening every object/subtype name usage with worries about limited
+views, you will significantly increase the implementation burden.
+
+...
+> - Replace 10.1.2(6) by:
+>
+> A library_item is *explicitly mentioned* in a with_clause if it is
+> denoted by a library_unit_name in the with_clause. A library_item is
+> mentioned in a nonlimited_with_clause if it is explicitly mentioned or
+> if it is denoted by a prefix in the with_clause. A library_item is
+> mentioned in a limited_with_clause if it is explicitly mentioned or if
+> it is denoted by a prefix in the with_clause, and that with_clause is
+> not more nested than a nonlimited_with_clause that mentions the same
+> library_item.
+>
+> [For nonlimited_with_clauses, this doesn't change the current RM. For
+> limited_with_clause, it says that if for instance the specification of Q
+> has a "with P" and the body of Q has a "limited with P.R.S" then P is
+> not mentioned in the limited_with_clause. So the limited_with_clause has
+> no effect for P; in particular it doesn't revert to the limited view of
+> P. On the other hand, it makes the limited views of P.R and P.R.S
+> visible. This is mostly a methodological restriction, as we have
+> (pathological) cases where the limited view hides the full view.
+> However, we want to make such cases infrequent, in part to avoid
+> confusing users, and in part to account for the fact that the checks
+> associated with "reverting" to a limited view may be a bit costly.]
+
+
+I think we might be able to simplify this by talking about the
+scope of a limited view of a package, and say that it is the scope of
+a limited with clause that mentions it minus the scope of any
+more nested (nonlimited) with clause that mentions it, or
+any renaming of it.  I presume we are still disallowing a
+limited with mentioning a library-unit renaming.
+
+> - Add after 10.1.2(8):
+>
+> A limited_with_clause which explicitly mentions a library_item shall not
+> be more nested than a nonlimited_with_clause which mentions the same
+> library_item.
+
+I think this is approximately equivalent to saying that a limited
+with clause is illegal if it has no effect (because it is immediately
+canceled by some outer or same-context-clause nonlimited with).
+Withs that "skip over" via renamings one of the enclosing packages
+mentioned in the limited with make this only an approximate equivalence.
+
+By the way, I think we may want to disallow a limited with of
+a package inside a "use" clause for a renaming of the package
+(or nested package thereof).  Or we need to make the "use"
+lose its effect.  In any case, I don't think we want to allow
+(new) "use" clauses of limited views of packages.
+
+...
+> - Add after 8.3(20):
+>
+> The full view of a library_item is hidden from all visibility within the
+> scope of a limited_with_clause that mentions it. The limited view of a
+> library_item is hidden from all visibility within the declarative region
+> of the library_item, and within the scope of a nonlimited_with_clause
+> that mentions it.
+
+I think you want to talk about library packages here rather than
+library "items", and make it clear that a non-limited with
+of a renaming of a library package also hides the limited view.
+Rather than talking about "hiding" the limited view, we could
+talk about its scope.  We might also want to talk about the
+scope of the full view instead of using hiding for that.
+Essentially the scope of the full view is as defined now,
+except it does not include places that are within the scope
+of the limited view.  The scope of the limited view is
+defined in terms of the scope of limited/non-limited with clauses
+that mention it (or a renaming thereof).
+
+...
+> - Replace 3.11.1(8) by:
+>
+> A type is completely defined at a place that is after its full type
+> definition (if it has one) and after all of its subcomponent types are
+> completely defined. Furthermore, if the type is declared within the
+> visible part of a library_item, it is *not* completely defined within
+> the scope of a limited_with_clause that mentions the enclosing
+> library_item. A construct that causes freezing of a type shall occur at
+> a place where the type is completely defined (see 13.14 and 7.3).
+
+This is where I think you are getting more complicated than
+necessary.  Rather than talking about whether a type is completely
+defined, I would talk only about what P.T denotes, when
+P is a limited view of a package.  I think you are asking
+for a *much* more complicated implementation effort if
+you are expecting every use of a type, including in subprogram
+bodies, to check to see whether it should be considered incomplete.
+Why not just say that within the limited view of a package P,
+"P.T", or "Q.T" where Q is any renaming of P, denotes
+an incomplete view of T.  Other subtypes declared using
+full views of T, or objects declared using full views of
+T, are not affected.  And of course, a limited view of
+a package only contains nested packages and incomplete
+type declarations, nothing else.
+
+...
+> - Replace 13.14(17) by:
+>
+> A construct that causes freezing of a type shall occur at a place
+> where the type is completely defined.
+
+Again, I don't think we need to muck with the freezing rules.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Thursday, March 27, 2003  10:55 AM
+
+> My major comment is that we should restrict ourselves to
+> talking about what is in the limited view of a package,
+> namely it contains limited views of nested packages, and
+> incomplete type declarations.  It seems unnecessary to go and
+> render incomplete other uses of a type declared in
+> the package, presuming those uses appeared in
+> places where a full view of the package existed
+> (e.g. objects of the type, or subtypes of the
+> type, or types derived from subtypes of the type,
+> or ...).
+
+I am confused here.  The problem I am trying to solve is the two-view
+problem, i.e. the situation where the compiler has to juggle with the
+limited and the full view of the unit.  My fear is that, if that if we
+don't have the "revert to incomplete" rule, the compiler will end up
+wandering in the symbol table for the full view of the unit, and we
+won't have solved the problem.
+
+Or maybe this won't happen, i.e. the compiler will never try to look at
+the full view of the unit?  Hmmm, not sure if all the rules of the
+language combine to prevent this problem from happening...
+
+This being said, I must admit that the notion of checking the freezing
+rules in statement parts is unappealing.
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Thursday, March 27, 2003  2:13 PM
+
+If you make all renames of the package show the limited view,
+and you disallow "use"s, then I don't see why you would be wandering
+in the package's full-view symbol table at all.  But your
+mileage may vary...
+
+> This being said, I must admit that the notion of checking the freezing
+> rules in statement parts is unappealing.
+
+And I think its worse than that.  Once we freeze something, we
+mark it frozen.  We would have to ignore that flag and, pretty
+much on every use, have to check whether the entity is declared
+somewhere inside a package that has its limited view in scope.
+Uggh.
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 27, 2003  6:11 PM
+
+I don't see that as particularly bad: it just means more work for the
+Check_Freezing subprogram. (Or whatever it's called). And if there are
+places where that's not called, they'd have to be added. I doubt that is
+anywhere near as much work as implementing limited views themselves.
+
+(But, of course, a better idea is welcome...)
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Friday, March 28, 2003  4:48 AM
+
+My opinion exactly.  And I doubt that is anywhere near as much work as
+juggling with two views and having to decide on each and every construct
+of the language which view you are allowed to access.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Thursday, March 27, 2003  3:32 PM
+
+> If you make all renames of the package show the limited view,
+> and you disallow "use"s, then I don't see why you would be wandering
+> in the package's full-view symbol table at all.  But your
+> mileage may vary...
+
+Consider the following example:
+
+    package P is
+        type T is tagged;
+        function "=" (L, R : T) return Boolean;
+    end P;
+
+    with P;
+    package Q is
+        type A is array (1..10) of T;
+        X, Y : A;
+    end Q;
+
+    with Q;
+    limited with P;
+    procedure Main is
+    begin
+        if Q.X = Q.Y then
+            ...
+        end if;
+    end Main;
+
+One code generation strategy for the equality in Main is to generate a loop
+calling P."=" for each component.  I fail to see how this can be done
+without accessing the full view of P.  In particular, a clever compiler
+might just want to use a block comparison if T has no user-defined "=", so
+it will surely need to look at the full view of P.
+
+Also, from the user standpoint, I think that operating on objects (or types)
+which have incomplete parts is counter-intuitive and can lead to all sorts
+of surprises.
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Thursday, March 27, 2003  4:58 PM
+
+I think we weren't understanding one another.  I certainly
+agree you need to get to the full view of the types declared
+in P, and all of their "basic" operations, because there
+might be subtypes, objects, derived types, etc. of them around.
+
+I just think you don't need to get to the full view of the
+package itself.  That is, while within the limited view of P,
+you don't need to do a lookup in the full symbol table of P.
+
+Perhaps what you are saying is that you do a *lookup* in P to
+find the primitive "=" on tagged T needed for creating a composite
+"="?  I guess that surprises me.  With this proposal, I think
+you will have to eliminate any such "implicit" lookups if you
+do them, and simply store on the type node a reference to its
+primitive "=" if it is tagged.
+
+The explicit operator lookups are fine, since the package cannot
+be used (and presumably, nor can any types declared in the package)
+while in the limited view of the package.  Hence the explicit
+operator lookups will never find anything.
+
+> Also, from the user standpoint, I think that operating on objects (or types)
+> which have incomplete parts is counter-intuitive and can lead to all sorts
+> of surprises.
+
+I agree.
+
+I don't think this is the way they should or would think about it.
+The parts don't become limited, just because we are in the limited
+view of a package where a part's type might have been defined.
+
+The key point is that anything already extracted out of the full view of
+the package is still fine.  You just can't extract anything
+more out of the package, while in its limited view.
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 27, 2003  6:20 PM
+
+Right. You're going to have to have the full view in your symboltable, like
+it or not. I know that Janus/Ada will fail spectacularly if a package in the
+semantic closure isn't loaded. (We had a number of bugs like that in the
+past.) So, there is no option to avoid loading the full views of everything
+in the semantic closure.
+
+But, we can't allow the package view to be full to some users and limited to
+others. And we can't just use the semantic dependence because of the ripple
+effects. So I think Tucker's proposal is about right. If the package was in
+the semantic closure, we'd use a subprogram to go through it and turn off
+the visibility bits of everything that is not a package or a type.
+That means that there would be only one lookup view. The other checking
+would have to be done at the point of use (there wouldn't be anyway to mark
+it) - presumably the code that determines if we have enough visibility to
+proceed from the incomplete view to the complete view would have to muck
+around in a list of with clauses. (I don't think that such a list exists
+currently.) If the view is limited, we don't allow moving to the complete
+view.
+
+But I'll have to think about this more to be sure that this is doable.
+
+**************************************************************
+
+From: Robert Eachus
+Sent: Thursday, March 27, 2003  5:06 PM
+
+I have been reading this ongoing discussion with stunned disbelief.  Not
+that the details are complex, or that some solution is required.
+It is just that for many of these problems, the simple solution is to
+make the complicating factors illegal.
+
+For example, the issue of renaming packages which contains potentially
+incomplete types.  The simple solution is to make it illegal to rename a
+package if the context clause doesn't contain the completion of any
+incomplete types in that package.
+
+The problem we are trying to solve could be solved by allowing
+implementations to require both the unit with the incomplete type and
+its completion to be compiled together.  I think that is a bit
+draconian, but I also think that some of the problem cases being
+discussed are a result of trying to make the rules for these types too
+orthogonal.
+
+I can live with some pretty severe restrictions to make such
+declarations available.  Not renaming packages with an incomplete view
+of a type is pretty mild.
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 27, 2003  6:29 PM
+
+> It is just that for many of these problems, the simple solution is to
+> make the complicating factors illegal.
+
+No, we can't do that, because that is precisely the ripple effect that we're
+trying to avoid: adding or removing a with clause on a distant unit changing
+the legality of a unit.
+
+> For example, the issue of renaming packages which contains potentially
+> incomplete types. The simple solution is to make it illegal to rename a
+> package if the context clause doesn't contain the completion of any
+> incomplete types in that package.
+
+That's not the issue at all. Look at the examples that Pascal posted more
+closely. The package which was renamed was a full view. The incomplete view
+is coming from the local package; the full view is coming from the semantic
+closure. The point of that example is that visibility isn't the right model,
+because with a renaming, we can have visibility onto the full view -- and
+thus even using a visibility model causes ripple effects.
+
+> The problem we are trying to solve could be solved by allowing
+> implementations to require both the unit with the incomplete type and
+> its completion to be compiled together.  I think that is a bit
+> draconian, but I also think that some of the problem cases being
+> discussed are a result of trying to make the rules for these
+> types too orthogonal.
+
+That's similar to what alternative 05 does for type stubs, but is much
+stronger. And I don't think it helps, but it makes it a lot harder to use
+these things (particularly if you want to avoid extra packages). Besides,
+"allowing" implementations to do something is not likely to be helpful if
+the implementation has no way to do anything with that (that's certainly
+true of Janus/Ada, which can only process one unit at a time, and I think it
+is true of Gnat as well).
+
+**************************************************************
+
+From: Robert Eachus
+Sent: Thursday, March 27, 2003  8:44 PM
+
+I think you are taking what I was saying a little too literally.  If it
+takes subtle analysis do decide when a renaming needs to be outlawed
+because it causes visibility clashes, fine.  All the user needs to know
+is that a renaming of a package with an incomplete type may be illegal
+in some contexts.  That won't bother many, if any, users.  (Most package
+renamings I see are either library renamings or abbreviations of
+predefined language units.)
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Thursday, March 27, 2003  9:21 PM
+
+Robert,
+    You are definitely confused about the issue.
+We have already agreed to disallow renaming
+of limited views.  What we are dealing with
+now are renamings that were done in a place which
+only saw the full view, and is totally unaware that
+a "limited with" even exists.  The problem is
+that a unit that has a limited-with might also
+"with", directly or indirectly, something that
+already has a rename of the full view.  This means
+that it can get at this renaming.  What should
+it see if it tries to use the renaming.  Should it
+see the full view, which was what existed when the
+renaming was declared, or should it see the
+limited view, which is all it can see by naming
+the package directly?
+
+In Pascal's proposal, you will see the limited view,
+even though when the renaming was declared, it was
+a renaming of the full view.  I think Pascal's
+proposal is the right answer here.  It gibes with
+what happens when you go through a renaming of
+a library unit with children.  The children you
+see are based on those that are visible at the
+point of reference to the renaming, rather than
+at the point where the renaming was declared.
+
+**************************************************************
+
+From: Robert Dewar
+Sent: Thursday, March 27, 2003  10:12 PM
+
+> That's similar to what alternative 05 does for type stubs, but is much
+> stronger. And I don't think it helps, but it makes it a lot harder to use
+> these things (particularly if you want to avoid extra packages). Besides,
+> "allowing" implementations to do something is not likely to be helpful if
+> the implementation has no way to do anything with that (that's certainly
+> true of Janus/Ada, which can only process one unit at a time, and I think it
+> is true of Gnat as well).
+
+Actually it is not true of GNAT at all, it is perfectly reasonable for GNAT to
+process multiple units in the sense of requiring some units to be around when
+another unit is compiled.
+
+**************************************************************
+
+From: Robert Eachus
+Sent: Thursday, March 27, 2003  11:09 PM
+
+Exactly the situation I thought I was addressing. ;-)  Pascal's approach
+of seeing the limited view is troubling, but I think we can outlaw the
+case without much pain.  Yes, it means making it illegal for a unit with
+a limited view of a type to also have a full view of the type.
+
+The problem case would seem to be a package that created many types
+completed in several other units.  This would say that in that case you
+couldn't use the completed versions of some types in the bodies of
+packages that completed other types.  This would occasionally require
+multiple child packages, some of which completed types, others that
+created objects of those types.  Shrug.
+
+If we are trying to compare several approaches on the assumption that
+they will cause minimal implementation pain, I think we should be
+willing to accept such limitations and see where it leads.  If one of
+the three approaches looks much better given such limitations, great.
+Then we can choose that approach, knowing that it is a workable solution
+and see how much we can extend it before the implementation difficulties
+become too great.  That is what I was driving at.
+
+The current approach seems to be to have full implementation designs for
+the most general version of each approach, and I think that that way
+lies madness.
+
+In this sense I think Robert Dewar's recent message is a breath of fresh
+air.  GNAT might or might not "take advantage" of some permitted
+implementation freedom.  That doesn't mean we should reject the
+potential restriction ahead of time.  If allowing the restriction now
+makes a particular approach acceptable, we can either argue the politics
+later, or accept the restriction for now, and look into removing it
+later.  An implementation restriction on a feature that currently
+doesn't exist is not a hardship for anyone.
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Thursday, March 27, 2003  9:37 PM
+
+Well I haven't seen a real answer to my suggestion:
+Being in the limited view of a package should have no
+effect on objects or subtypes declared using the
+full view.  The only effect should be on what you
+get if you (explicitly) look up P.T, or renaming-of-P.T, and what
+you get is an incomplete view of T.  But there might
+be full views of T already embedded in objects or
+subtypes or derived types or composite types, and
+none of those are affected.  If implicit lookups
+in P are needed to support these preexisting
+objects/subtypes/derived types, then those implicit
+lookups should use the full view, but these should
+be rare, and could probably be handled in some other
+way (e.g., hanging the primitive "=" directly off
+the type, rather than having to look it up each
+time it is needed to implement the equality of
+an enclosing composite object).
+
+I think this eliminates any need to futz/muck/mess
+with freezing rules, and localizes the changes to
+explicit package lookups.
+
+This is reminiscent of what we already do for
+library packages.  We have the original view
+of a package, and then we construct an "augmented"
+view when a package is "with"ed, and in the augment
+view we add children that get "with"ed.  The original
+view is preserved in a read-only state.  The
+augmented view is built up incrementally during
+context clause processing.
+
+I could see also having a "limited" view for a package.
+It could be constructed based on the full view if available,
+or by doing a "loose parse" of the source of the package.
+This limited view would be used for all explicit lookups
+in the package when the limited view is in scope
+due to mention in a limited with clause (and not
+"canceled" due to mention in an inner non-limited "with").
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Friday, March 28, 2003  4:47 AM
+
+First, let me make clear that from my perspective, the Ripple Effect
+Problem is way more severe than the Two-View Problem.  The former is a
+no-no for me, as it kills incremental compilation.  The latter is a
+nuisance, but if I absolutely have to, I suppose I can live with it.
+
+So my objection to your position, Tucker, is that, if you don't have the
+"revert to incomplete" rule, the language design looks botched.  For
+instance:
+
+    package P is
+        type T is ...;
+    end P;
+
+    with P;
+    package Q is
+        type T is
+            record
+                C : P.T;
+            end record;
+    end Q;
+
+    limited with P;
+    with Q;
+    package Main is
+        X : P.T; -- Illegal
+        Y : Q.T; -- Legal
+    end Main;
+
+The fact that the declaration of X is illegal but the declaration of Y
+is legal looks like a wart to me.  Try to explain this to real users!
+It would seem much more natural to say that they are both illegal.
+
+As I understand it, you main objection is one of implementation
+complexity (I don't buy arguments based on the number of words in the RM
+that have to change).  Since all incarnations of AI 217 will require a
+lot of work anyway, I cannot get too excited.  It seems to me that we
+should concentrate on finding a nice and clean language mechanism, even
+if that's at the expense of some implementation complexity.
+
+> I think we weren't understanding one another.  I certainly
+> agree you need to get to the full view of the types declared
+> in P, and all of their "basic" operations, because there
+> might be subtypes, objects, derived types, etc. of them around.
+>
+> I just think you don't need to get to the full view of the
+> package itself.  That is, while within the limited view of P,
+> you don't need to do a lookup in the full symbol table of P.
+>
+> Perhaps what you are saying is that you do a *lookup* in P to
+> find the primitive "=" on tagged T needed for creating a composite
+> "="?  I guess that surprises me.
+
+After checking the code, it turns out that we don't in this case.  But
+there are other situations where we do.  For instance:
+
+    package P is
+        type T is ...;
+        function F return T;
+    end P;
+
+    with P;
+    package Q is
+        subtype S is P.T;
+    end Q;
+
+    limited with P;
+    with Q;
+    package Main is
+        type NT is new Q.S;
+    end Main;
+
+In order to build the inherited subprograms for NT, we scan the
+declarative part where T is declared, i.e. the full view of P.  And we
+are certainly not going to change this, it would be way too disruptive.
+If we had to implement the rules that you propose, we would have to live
+with the Two-View Problem.  But again, my objection is mostly one of
+language design.
+
+> And I think its worse than that.  Once we freeze something, we
+> mark it frozen.  We would have to ignore that flag and, pretty
+> much on every use, have to check whether the entity is declared
+> somewhere inside a package that has its limited view in scope.
+
+I realize that implementation complexity depends a lot on how things are
+structured.  However I am a bit surprised by your claim, because for us
+changing the freezing rules to deal with type "reverting to incomplete"
+would literally be an afternoon project.  Let me give a few
+implementation notes to make the discussion more concrete.
+
+When a type gets frozen we do mark it with a bit, Sm_Frozen, in the
+Diana tree.  It turns out that we run the freezing checks on statement
+parts as well as declarative parts, because some constructs in statement
+parts declare anonymous subtypes that need to get frozen (don't ask).
+Most of the time this processing ends very quickly because it finds that
+Sm_Frozen is set.  But I realize that this is an idiosyncrasy of our
+implementation, and that most compilers probably don't look at statement
+parts.
+
+To implements the "revert to incomplete" rule, I would probably have a
+global bit indicating whether or not I am in the scope of a limited
+with.  (I could be more clever and only set this bit when I am in the
+scope of a "limited with P" and P is in the closure through some other
+path, but I guess that I would be too lazy to do that.)  During the
+freezing checks, this global bit would cause the setting of Sm_Frozen to
+be ignored, so we would effectively traverse the subcomponents, etc. of
+each type.  Once a type has been found to be OK (i.e., to not have any
+incomplete subcomponent) I would mark it with a temporary bit so as to
+avoid redoing the traversal over and over again.  This means that every
+type would be analyzed (at most) once, so the performance impact should
+be minimum.  Obviously there would be no performance impact at all when
+you are not in the scope of a limited with.
+
+This doesn't sound like rocket science to me.  Could you maybe explain
+your implementation concerns in a bit more detail?
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Friday, March 28, 2003  4:54 AM
+
+> Well I haven't seen a real answer to my suggestion:
+> Being in the limited view of a package should have no
+> effect on objects or subtypes declared using the
+> full view.  The only effect should be on what you
+> get if you (explicitly) look up P.T, or renaming-of-P.T, and what
+> you get is an incomplete view of T.  But there might
+> be full views of T already embedded in objects or
+> subtypes or derived types or composite types, and
+> none of those are affected.
+
+If you want my "real answer" to this it is that this approach really
+looks like a hack and is going to puzzle users.
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Friday, March 28, 2003  8:28 AM
+
+ > So my objection to your position, Tucker, is that, if you don't have the
+ > "revert to incomplete" rule, the language design looks botched.
+
+I don't agree, but in any case, we should agree we
+are talking about corner cases here, because this only
+occurs when you are in the scope of a limited view, but
+the full view is in your semantic closure.  Hence, I believe
+as few words and as little implementation complexity should be
+devoted to this area as possible, subject to eliminating
+ripple effects.  I believe the key thing is to limit ourselves
+to talking about limited views of *packages*, and not get
+hung up on imposing limited views on anything else.
+Packages are already a bit funny because of public/private
+children and visible/private parts.
+
+ > For
+ > instance:
+ >
+ >     package P is
+ >         type T is ...;
+ >     end P;
+ >
+ >     with P;
+ >     package Q is
+ >         type T is
+ >             record
+ >                 C : P.T;
+ >             end record;
+ >     end Q;
+ >
+ >     limited with P;
+ >     with Q;
+ >     package Main is
+ >         X : P.T; -- Illegal
+ >         Y : Q.T; -- Legal
+ >     end Main;
+ >
+ > The fact that the declaration of X is illegal but the declaration of Y
+ > is legal looks like a wart to me.
+
+It doesn't look like a wart to me, because the types used to
+implement Q.T are the business of Q, and should not be
+relevant to a user of Q.  Suppose Q.T were implemented in
+terms of U.T, which is implemented in terms of V.T, which
+is implemented in terms of W.T, which just happens to have
+a teeny little component in one of its many variant parts that
+happens to be of a type that is derived from P.T?
+
+Or suppose we change Q to:
+
+    with P;
+    package Q is
+        type R is private;
+        ...
+    private
+        type R is record
+            C : P.T;
+        end record;
+    end Q;
+
+Clearly with your defender-of-privacy hat on,
+you wouldn't want the characteristics of R to
+be affected when a user of Q happens to have
+a limited view of P.
+
+ > ...  Try to explain this to real users!
+
+The key is that the compilation unit has a limited view of *P*,
+so it can only see certain things in P, and it sees only
+some features of those via an expanded name involving P
+(or one of its renamings).  It doesn't affect any other
+compilation unit, nor any names that don't involve P or
+one of its renamings.
+
+ > It would seem much more natural to say that they are both illegal.
+
+I don't agree, and I really think this way lays big trouble.
+Suppose you instantiate a generic, which instantiates a
+generic, which declares an object of a derived type of P.T.
+I really think you are recreating a ripple effect, where
+some distant package's decision to use something from
+P affects whether you can instantiate it.
+
+
+ >
+ > As I understand it, you main objection is one of implementation
+ > complexity (I don't buy arguments based on the number of words in the RM
+ > that have to change).
+
+I agree that number of words is not a great guage, but it
+is relevant, and especially when you are affecting the
+legality of essentially every construct in the language.
+
+Would it be legal to call a subprogram that had a default
+expression that happened to use a 'Access attribute of an
+object of type P.T?  Or how about use a record type where one of
+the components had a default expression that referenced the
+identity attribute of an exception declared in P?
+
+ > ...  Since all incarnations of AI 217 will require a
+ > lot of work anyway, I cannot get too excited.  It seems to me that we
+ > should concentrate on finding a nice and clean language mechanism, even
+ > if that's at the expense of some implementation complexity.
+
+Well, I believe your proposal is much cleaner if you focus
+strictly on what you can see when you explicitly try
+to refer to components of a limited view of a package
+via an expanded name.
+
+You are opening an unnecessary can of very nasty worms
+if you start changing the characteristics of things
+in other compilation units, other than renamings of
+this same package.
+
+...
+ > In order to build the inherited subprograms for NT, we scan the
+ > declarative part where T is declared, i.e. the full view of P.  And we
+ > are certainly not going to change this, it would be way too disruptive.
+ > If we had to implement the rules that you propose, we would have to live
+ > with the Two-View Problem.  But again, my objection is mostly one of
+ > language design.
+
+I guess we have a list of primitives hanging off every type, so
+we never have to scan the package itself, but I agree, deriving
+is probably tricky.  But again, what happens if the type you
+are deriving from is a private extension of some ancestor of
+P.T, but when you get into the private part, you discover its
+immediate parent is P.T itself.  I really think this shouldn't
+affect legality of the new type derivation.
+
+ >>And I think its worse than that.  Once we freeze something, we
+ >>mark it frozen.  We would have to ignore that flag and, pretty
+ >>much on every use, have to check whether the entity is declared
+ >>somewhere inside a package that has its limited view in scope.
+ >
+ >
+ > I realize that implementation complexity depends a lot on how things are
+ > structured.  However I am a bit surprised by your claim, because for us
+ > changing the freezing rules to deal with type "reverting to incomplete"
+ > would literally be an afternoon project.  Let me give a few
+ > implementation notes to make the discussion more concrete.
+ > ...
+ > This doesn't sound like rocket science to me.  Could you maybe explain
+ > your implementation concerns in a bit more detail?
+
+I don't want to focus the argument on our implementation
+complexity, because I think the argument can be better
+focused on areas like privacy and ripple effects which
+I know are near-and-dear to your heart.
+
+But in general, I think making this proposal depend
+subtly on the freezing rules, and what is
+frozen by what sorts of uses, is a mistake, and
+completely unnecessary to achieve all of your objectives.
+
+As I said in my first paragraph, we are talking about
+corner cases, and they don't deserve the effort that
+will be involved in defining exactly what is legal when using
+entities that in some vague way depend on the full
+view of P.  Renamings of P are clear, everything else
+just gets muddier and muddier in my view.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Friday, March 28, 2003  8:48 AM
+
+> I don't agree, but in any case, we should agree we
+> are talking about corner cases here, because this only
+> occurs when you are in the scope of a limited view, but
+> the full view is in your semantic closure.
+
+I definitely agree that this is a corner case.  I still think it's
+important to come up with a model that is not too surprising to users,
+and consistent with the rest of the language.  But if we can't, I'm not
+going to throw the baby with the bathwater.
+
+> Or suppose we change Q to:
+>
+>     with P;
+>     package Q is
+>         type R is private;
+>         ...
+>     private
+>         type R is record
+>             C : P.T;
+>         end record;
+>     end Q;
+>
+> Clearly with your defender-of-privacy hat on,
+> you wouldn't want the characteristics of R to
+> be affected when a user of Q happens to have
+> a limited view of P.
+
+That's a rather compelling argument, and I need to give it more thought
+over the week-end.  Of course, my immediate answer would be to say that
+you have to assume-the-worst for private types, but I'm not sure I like
+that, because it would disallow perfectly reasonable usages of perfectly
+good private types.
+
+> I don't want to focus the argument on our implementation
+> complexity, because I think the argument can be better
+> focused on areas like privacy and ripple effects which
+> I know are near-and-dear to your heart.
+
+Right, language design, not implementation complexity, should be the
+focus here.
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Friday, March 28, 2003  7:24 PM
+
+> I guess we have a list of primitives hanging off every type, so
+> we never have to scan the package itself, but I agree, deriving
+> is probably tricky.  But again, what happens if the type you
+> are deriving from is a private extension of some ancestor of
+> P.T, but when you get into the private part, you discover its
+> immediate parent is P.T itself.  I really think this shouldn't
+> affect legality of the new type derivation.
+
+Yuck! This example gives me heartburn, precisely because we do exactly what
+Rational does. It MIGHT work anyway (because I think that the visibility
+bits are ignored for the purposes of derivation - but I'm not at all sure
+about that) -- that's a very fragile area, and I hate the idea of having to
+muck with it because of some completely unrelated feature.
+
+I guess what worries me here is that we're going to end up with two views in
+all cases except those that cause ripple effects -- which is hardly going to
+help implementation or usability.
+
+But I don't see a showstopper here. And I certainly agree that this is a
+corner case; having it perfect isn't critical. (The same can be said about
+dereferencing rules, BTW, because the only cases that we'd be worrying about
+are the same ones as here: where we're in the semantic closure of P but only
+have a limited view. For type stubs, that's where we're in the semantic
+closure of the completing type, but only have visibility on the incomplete
+type. Neither sounds real likely.)
+
+**************************************************************
+
+From: Dan Eilers
+Sent: Friday, March 28, 2003 11:10 AM
+
+> The fact that the declaration of X is illegal but the declaration of Y
+> is legal looks like a wart to me.  Try to explain this to real users!
+> It would seem much more natural to say that they are both illegal.
+
+This looks easy to explain to real users by citing the rule that
+adding a "with" clause to a unit can't make anything in the unit
+illegal that was previously legal.  The rule is just being extended
+to "limited with" clauses.
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Friday, March 28, 2003 11:42 AM
+
+I agree with this principle, and we should try to preserve it, though it isn't
+quite true for "with" clauses, and it won't be true with limited with if you
+already refer to a renaming of the package (which is admittedly a real corner
+case).  But I agree that adding a limited with for package P should not affect
+the legality of anything in the compilation unit other than existing references
+to package P or renamings thereof (or nested packages thereof).
+
+It isn't quite true for "with" clauses because adding a "with" clause can hide
+something that was "use" visible.  E.g.:
+
+   package P1 is
+       type P2 is (tbd);
+   end P1;
+
+   with P1; use P1;
+   with P2;  -- Makes decl of X illegal
+   procedure Main is
+       X : P2;  -- becomes illegal
+   begin null end;
+
+But if the name "P2" doesn't appear in the compilation unit, then adding
+a "with" clause for P2 cannot make anything illegal.
+
+**************************************************************
+
+From: Robert I. Eachus
+Sent: Friday, March 28, 2003  7:37 PM
+
+> I agree with this principle, and we should try to preserve it, though
+> it isn't quite true for "with" clauses, and it won't be true with limited
+> with if you already refer to a renaming of the package (which is admittedly
+> a real corner case).  But I agree that adding a limited with for package P should
+> not affect the legality of anything in the compilation unit other
+> than existing references to package P or renamings thereof (or nested packages thereof).
+
+I can't believe I can see this so clearly, and the everyone else keeps
+looking at the trees.  Let me try to explain my logic, and see if you
+can punch holes in it.  Something is wrong, and I suspect that I am just
+not communicating my point clearly enough....
+
+Thesis:  It should be illegal for a context to include a  "limited with
+P;" clause if the remainder of the context semantically depends on P.
+
+In other words, if "limited with P;" doesn't add visibility while
+preventing a semantic dependence on P, someone is making a mistake.
+
+The whole idea of "limited with" is that a unit with a "limited with P;"
+does not semantically depend on P.  If a unit semantically depends on P
+for some other direct or indirect reason, then a "limited with P;" is at
+best a waste of breath.  I argue that we should just make it illegal.
+There is an error somewhere.  We don't know where.  But trying to make
+complex rules and add lots of compiler support for something which is
+not just a corner case but ALWAYS an error is silly.
+
+The same type of logic holds in the alternative proposals.  In every
+case we should remember what the goal is, and not try to add bells and
+whistles that are of no possible use.  In the child package approach, we
+want to create child packages that do not semantically depend on their
+parents.  Cases where a child both does and does not semantically depend
+on the parent (directly or indirectly) are both logically impossible and
+silly.
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Friday, March 28, 2003  8:01 PM
+
+> In other words, if "limited with P;" doesn't add visibility while
+> preventing a semantic dependence on P, someone is making a mistake.
+
+Yes, of course. But we can't prevent that.
+
+> The whole idea of "limited with" is that a unit with a "limited with P;"
+> does not semantically depend on P.  If a unit semantically depends on P
+> for some other direct or indirect reason, then a "limited with P;" is at
+> best a waste of breath.  I argue that we should just make it illegal.
+> There is an error somewhere.  We don't know where.  But trying to make
+> complex rules and add lots of compiler support for something which is
+> not just a corner case but ALWAYS an error is silly.
+
+We tried that. But that is a severe ripple effect, and such an effect kills
+incremental compilation -- which means that Rational cannot support such a
+feature in their Ada compiler. We can't be putting vendors out of the Ada
+business in this Amendment! We don't have enough as it is.
+
+In case you don't see the problem, consider the program:
+
+    package P is
+        type T is tagged ...
+        type Index is ...
+    end P;
+
+    package Q is
+        procedure Proc ...
+    end Q;
+
+    with Q;
+    limited with P;
+    package R is
+        type Acc is access all P.T'Class;
+    end R;
+
+We all agree this is legal.
+
+Now, imagine that during maintenance, someone decides that they need a
+version of Proc that takes an Index. So, they change Q to:
+
+    with P;
+    package Q is
+        procedure Proc ...
+        procedure Proc (I : in P.Index; ...);
+    end Q;
+
+Now, by your rule, R is now illegal. That's the ripple effect; for a
+compiler like Rational's, every compilation unit that might semantically
+depend on Q has to be checked. In real systems, that's pretty much
+everything.
+
+Note that Q doesn't depend on P.T at all, it just happens to depend on
+something that's coincidentally in P.
+
+That tends to suggest that Tucker is right in the discussion he and Pascal
+are having. Indeed, it seems that there would be a ripple effect with
+Pascal's rule: if someone adds an Index component to some type in Q, that
+would make uses of that type illegal in R. I can't imagine that's what
+Pascal wants.
+
+    package Q1 is
+       type Priv is private;
+    private
+       type Priv is record
+          A : Integer;
+       end record;
+    end Q1;
+
+    with Q1;
+    limited with P;
+    package R1 is
+        type Acc is access all P.T'Class;
+        Obj : Q1.Priv;
+    end R1;
+
+All is OK here. Now, if a maintenance programmer changes Q1 to get better
+type checking:
+
+    with P;
+    package Q1 is
+       type Priv is private;
+    private
+       type Priv is record
+          A : P.Index;
+       end record;
+    end Q1;
+
+    with Q1;
+    limited with P;
+    package R1 is
+        type Acc is access all P.T'Class;
+        Obj : Q1.Priv; -- Illegal by Pascal's proposed rules.
+    end R1;
+
+That looks like a second-hand ripple effect to me. It's especially annoying
+because P.Index is never used as an incomplete type. (The big possible
+annoyance with limited with is the lack of control over what becomes
+incomplete. Here we see that it can be too much.)
+
+**************************************************************
+
+From: Robert I. Eachus
+Sent: Friday, March 28, 2003  8:42 PM
+
+> We tried that. But that is a severe ripple effect, and such an effect kills
+> incremental compilation -- which means that Rational cannot support such a
+> feature in their Ada compiler. We can't be putting vendors out of the Ada
+> business in this Amendment! We don't have enough as it is.
+
+Now I see what you are worried about, but I still don't see it as
+specific to this feature.  If instead, package Q was changed so that
+Proc required a new parameter, then any unit that depended on Q might
+become illegal.  Sure this new rule would means that modifying any unit
+that R depends on by adding a with P will make R illegal, and that would
+mean adding a new check.  But I just don't see any better solution.
+
+In reality, as I said we will see very few cases where a unit with a
+limited with will be in some metric "distant" from the unit it does't
+depend on. ;-)  If we have to come up with some restrictive rule that
+makes it easier for Rational, lets do that.  But I think that trying to
+make the dual path work is a waste of effort.
+
+Let me take your example and extend it a bit...
+
+     with R; -- added
+     package P is
+         type T is tagged record
+                X: R.Acc; -- added
+                ...
+            end record;
+         type Index is ...
+     end P;
+
+     package Q is
+         procedure Proc ...
+     end Q;
+
+     with Q;
+     limited with P;
+     package R is
+         type Acc is access all P.T'Class;
+     end R;
+
+Still legal right?  Now add your with P to package Q:
+
+     with P;
+     package Q is
+         procedure Proc ...
+         procedure Proc (I : in P.Index; ...);
+     end Q;
+
+and there is NO EASY WAY to make the program legal.  It is not a minor
+detail, it is a major design problem.  And this will be the normal case.
+  The only reason to have limited with is to break cycles.  If a
+"limited with P;" can be added to Q, then you are okay.  So my
+understanding is that this example is a red herring.  The real ripple
+effect is that you can't add a with P; you have to add a limited with P;
+to Q if you want things to compile.
+
+**************************************************************
+
+From: Robert I. Eachus
+Sent: Friday, March 28, 2003  11:52 PM
+
+I did some more thinking about this example and mapped it to the
+"classic" example using employees and offices.  The surprise is that
+adding a dual path does not make the program illegal--at least without
+my proposed rule--but the "harmless" maintenance change does even more
+violence to the program structure:
+
+limited with Employees;
+package Offices is
+   type Office is tagged private;
+   type Office_Pointer is access all Office'Class;
+   ...
+private
+   type Office is tagged record
+     ...
+      Occupant: Employee_Pointer;
+     end record;
+end Offices;
+
+limited with Offices;
+with Perks;
+package Employees is
+   type Employee is tagged private;
+private
+   type Employee is tagged record
+     ...
+     Assigned_Office: Office_Pointer;
+     Bonus_Package: Perks.Goodies;
+   end record;
+end Employees;
+
+with Offices;
+package Perks is
+   type Goodies is tagged private;
+private
+   type Goodies is tagged record
+     ...
+     Corner_Office: Office_Pointer;
+   end record;
+end Perks;
+
+Now in my proposal, a cowboy maintainer when he added the Corner_Office
+to the list of possible perks could go ahead and change the limited with
+Offices; to with Offices; and assuming that doing so did not cause any
+naming conflicts, the program would now compile.  The careful maintainer
+would add a subclass, say Executive, to Employee and put it in a
+separate package that would not need a with or limited with for Offices.
+
+Without my rule, the limited with on Employees is now a lie.  When
+another cowboy maintainer comes along and wants to add a with clause to
+Offices, he will need a fairly sophisticated tool--hopefully a part of
+the compiler or linker error messages--to tell him what has gone wrong.
+
+So as I see it, with my rule (you can't have a limited with Foo; on a
+unit that already depends on the Foo) USERS should be happy.  Without it
+you may find the same objections as to earlier proposals, that the
+context clause does not accurately describe the dependencies.  It may be
+that the proposal needs to be further modified to make it easier for
+Rational to do incremental compilation, but I just don't see it.  It is
+just one more constraint that has to be checked when a unit is modified.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Monday, March 31, 2003  4:24 AM
+
+> That looks like a second-hand ripple effect to me. It's especially
+> annoying because P.Index is never used as an incomplete type.
+
+I agree that there's a ripple effect here.  However it's not too bad
+from my perspective: if I have to disable incremental compilation in the
+child units and body when a limited_with is added to a spec, that's a
+nuisance, but I can live with it: it's not going to have a huge impact.
+Compare this with having to disable incremental compilation in the
+entire universe when any with_clause or renaming changes (that would not
+be acceptable).
+
+This being said, it would be better if the language were free of ripple
+effects.
+
+But to me the compelling argument is the breach of privacy: since I
+don't think that assuming-the-worst is acceptable, I guess I will have
+to agree (somewhat reluctantly) with Tucker's position.
+
+> (The big possible
+> annoyance with limited with is the lack of control over what becomes
+> incomplete. Here we see that it can be too much.)
+
+Right, but we are not going to give control on a declaration basis.  I
+think the right answer here is that you can use child units to structure
+your code appropriately: put the declarations that don't need to become
+incomplete in the parent, and in a child put exclusively those types
+that need to become incomplete.  Of course, you probably don't want to
+do that on existing code, as it could entail major restructuring.  But
+on new code, this is a perfectly sensible way to organize things.
+
+> However, any solution that requires writing two things is going to be
+> inferior to a solution that requires writing one. So, I suspect that
+> alternative 6 ("limited with") is likely to carry the day based on
+> better usability, even if it gives some implementers heartburn.
+
+Randy has seen the light.  ;-)
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Monday, March 31, 2003  1:29 PM
+
+I think we all would say "limited with" has a nice "feel" about it.
+The big issue is implementability.  Eliminating the affects on
+other compilation units resolves my main concern.  I think there might
+still be some issue for folks with fat and thin pointers (e.g. GNAT), but they
+don't seem worried, so why should I be?  We will have to implement
+a pretty big chunk of code to build up the limited view from a
+"quick-and-dirty" parse of a package.  I think "type T.C;" could
+be significantly easier to implement.  But if the consensus is
+to go with "limited with," I am "on board."
+
+**************************************************************
+
+From: Robert Dewar
+Sent: Monday, March 31, 2003  2:24 PM
+
+Well GNAT allows the use of thin or fat pointers, although I am not sure
+this is a problem in any case.
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Monday, March 31, 2003  5:39 PM
+
+> > (The big possible
+> > annoyance with limited with is the lack of control over what becomes
+> > incomplete. Here we see that it can be too much.)
+
+> Right, but we are not going to give control on a declaration basis.
+
+Every proposal other than alternative 6 (limited with) does have control on
+a declaration basis. Moreover, the lack of such control has been an
+annoyance in Ada since it was invented (this isn't a new problem with
+'limited with'; it's a problem with all with clauses).
+
+> I think the right answer here is that you can use child units to structure
+> your code appropriately: put the declarations that don't need to become
+> incomplete in the parent, and in a child put exclusively those types
+> that need to become incomplete.  Of course, you probably don't want to
+> do that on existing code, as it could entail major restructuring.  But
+> on new code, this is a perfectly sensible way to organize things.
+
+"Can" is certainly true, but "desirable" is in the eye of the beholder.
+Here, you're taking the other side (Tuck's side) of the same argument that
+has typically been used against type C.T;. I don't think proposals should
+have to rely on "structuring" in order to work; we don't want to impose a
+structure on users of Ada - they should be allowed to use their own design.
+
+In particular, I prefer to keep the ancillary types with the main O-O type.
+Most O-O types have some types (typically elementary) that are used to help
+define the operations for the main type - such as discriminants, lengths,
+etc. I strongly disagree with Robert Eachus' contention that such types
+indicate that something is wrong with the design.
+
+For instance, Claw.Image_List includes:
+
+package Claw.Image_List is
+    type Root_Image_List_Type is abstract new Ada.Finalization.Controlled
+...
+
+    type Color_Kind_Type is (
+        Default_Color_Scheme,
+        Color_4_Bit,
+        Color_8_Bit,
+        Color_16_Bit,
+        Color_24_Bit,
+        Color_32_Bit,
+        Color_Device_Dependent);
+
+    type Image_List_Index_Type is new Claw.Natural_Int;
+
+    type Overlay_Index_Type is new Claw.Natural_Int range 0 .. 15;
+    NO_OVERLAY : constant Overlay_Index_Type := 0;
+
+    function Get_Image_Count (List : in Root_Image_List_Type)
+        return Claw.Image_List.Image_List_Index_Type;
+        -- Returns the number of images in List.
+
+    procedure Set_Image_Count (List : in Root_Image_List_Type;
+                               New_Count : in Claw.Image_List.Image_List_Index_Type);
+        -- Sets the number of images in List.
+
+    ...
+
+end Claw.Image_List;
+
+I prefer to keep these extra types with the root type, as they can only be
+used with that type. Putting them in a separate package just means more
+times that you have to go searching for the declaration (if you use a lot of
+use clauses) or more noise in the text (if you use fully expanded names).
+
+> > However, any solution that requires writing two things is going to be
+> > inferior to a solution that requires writing one. So, I suspect that
+> > alternative 6 ("limited with") is likely to carry the day based on
+> > better usability, even if it gives some implementers heartburn.
+>
+> Randy has seen the light.  ;-)
+
+I don't think that's quite the right description. It's more that the Ada
+community as a whole is not likely to give too much weight to the
+implementability of a feature, and that whatever is nasty about 'limited
+with' is not going to visible to average users until it was been implemented
+in compilers for a while. So I thinks users will prefer 'limited with', and
+there isn't going to be a obvious 'show stopper' for it.
+
+On the other hand, unless there is some major revelation when I do the
+implementation analysis (either way) or a customer with $$$, I don't see RRS
+being able to afford the implementation costs for 'limited with'. A
+simplified version of alternative 4 will meet our immediate needs with what
+appears to be far less work.
+
+But, our implementation needs should not stand in the way of what probably
+will be judged to be the best solution.
+
+Tucker said:
+> I think we all would say "limited with" has a nice "feel" about it.
+> The big issue is implementability.  Eliminating the affects on
+> other compilation units resolves my main concern.  I think there might
+> still be some issue for folks with fat and thin pointers (e.g. GNAT), but they
+> don't seem worried, so why should I be?  We will have to implement
+> a pretty big chunk of code to build up the limited view from a
+> "quick-and-dirty" parse of a package.  I think "type T.C;" could
+> be significantly easier to implement.  But if the consensus is
+> to go with "limited with," I am "on board."
+
+Which is pretty much where I stand (with the exception of the remark about
+"type T.C"). I don't see any reason why 'limited with' couldn't be
+implemented - the amount of work involved is unlikely to be of interest to
+users.
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Monday, March 31, 2003  6:31 PM
+
+> Now in my proposal, a cowboy maintainer when he added the Corner_Office
+> to the list of possible perks could go ahead and change the limited with
+> Offices; to with Offices; and assuming that doing so did not cause any
+> naming conflicts, the program would now compile.  The careful maintainer
+> would add a subclass, say Executive, to Employee and put it in a
+> separate package that would not need a with or limited with for Offices.
+
+You didn't show the original program, which is important, because it appears
+to be illegal. If Perks originally had a 'limited with Offices' in it (or
+Perks doesn't exist at all), "Assigned_Office: Office_Pointer;" in Employees
+is illegal, because Office_Pointer is incomplete.
+
+In any case, this is not the case that I'm interested in. I was interested
+in the case where one of the related elementary types that declared with
+these types gets used. See my answer to Pascal for a real-life example of
+what I'm talking about.
+
+Or, to use your example (made legal assuming AI-230):
+
+limited with Employees;
+package Offices is
+   type Office is tagged private;
+   type Window_Count is range ...;
+   ... -- Operations.
+private
+   type Office is tagged record
+     ...
+      Occupant : access Employees.Employee'Class;
+      Windows : Window_Count;
+     end record;
+end Offices;
+
+-- Employees remains the same.
+
+package Perks is
+   type Goodies is tagged private;
+   ... -- Operations.
+private
+   type Goodies is tagged record
+       Dental_Insurance : Boolean := False;
+       Disability_Insurance : Boolean := False;
+   end record;
+end Perks;
+
+Now, imagine that we got a call on Friday that we have to add support for a
+minimum number of windows as a Perk by the end of the quarter (today is a
+particularly good day for this example :-).
+
+The obvious fix which preserves strong typing is:
+
+with Offices;
+package Perks is
+   type Goodies is tagged private;
+   ... -- Operations.
+private
+   type Goodies is tagged record
+       Dental_Insurance : Boolean := False;
+       Disability_Insurance : Boolean := False;
+       Minimum_Windows : Offices.Window_Count := 0;
+   end record;
+end Perks;
+
+One could argue that the type Window_Count should be moved somewhere else,
+but that is unlikely for two reasons: 1) The number of windows is a property
+of an Office - it isn't very meaningful by itself; 2) The time allotted for
+the change means that major restructuring has to be avoided if at all
+possible.
+
+This is often how I have to do maintenance: when a customer has a critical
+bug, you have to find a way to fix it, design be damned. If the fix is a
+real mess, I'll note that and try to schedule some time to redo the code.
+But that often doesn't happen for months or even years, because that sort of
+cleanup rarely helps the customers or attracts new ones.
+
+> Without my rule, the limited with on Employees is now a lie. ...
+
+Not really. Employees is essentially doing a 'with type
+Employees.Employee;'. The only problem is that 'Window_Type' is getting
+dragged along as well (a type we don't even use in Employees). That, of
+course, is a standard problem with with_clauses in Ada, it certainly isn't
+new here. But we don't want rules that make that clearly obvious.
+
+> So as I see it, with my rule (you can't have a limited with Foo; on a
+> unit that already depends on the Foo) USERS should be happy. Without it
+> you may find the same objections as to earlier proposals, that the
+> context clause does not accurately describe the dependencies.
+
+Ada with_clauses are too coarse to accurately describe dependencies (unless
+you restrict yourself to one declaration per package -- which I doubt many
+people do). I don't see that we can do better (or should try to do better)
+with 'limited with'.
+
+In any case, this maintenance change doesn't suddenly make the original
+design invalid, and it's unlikely to confuse the programmer. But your rule
+(or Pascal's, for that matter) might make it a lot harder to fix a problem
+and preserve strong typing. In the example above, if various units become
+illegal from adding the 'with Office;', the programmer (who is under severe
+time constraints) is likely to toss the strong typing and just make the
+number of windows an Integer. I don't think we want language rules which
+encourage that.
+
+> It may be that the proposal needs to be further modified to make it easier for
+> Rational to do incremental compilation, but I just don't see it.  It is
+> just one more constraint that has to be checked when a unit is modified.
+
+I'd be interested to know Pascal's opinion on this proposal. It seems that
+he's said that it would be unacceptable, but I'm not certain. Robert's rule
+would require rechecking all possible dependents [at least to see if they
+have a limited with] when a with_clause is added, even those that don't
+directly with the unit. I believe that currently only units that have a with
+for the changed unit need to be checked, so that potentially would be a
+significant change.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, April 1, 2003  3:09 AM
+
+This is just another argument against my "revert to incomplete" rule and
+in favor of Tuck's approach.  But then I think I have come to agree that
+Tuck is right anyway because of the interaction with private types.
+
+I actually think that in this example the quick-and-dirty fix is to use
+Natural for component Minimum_Windows, and to come back later to do more
+extensive restructuring.  The reason is that we are getting pretty close
+to a situation where a cycle that involved two packages (Employees and
+Offices) must be extended to involve a third package (Perks).  This is
+particularly true if you take operations into account.  For instance, in
+order to assign offices to employees, the package Offices may have to
+export an operation like:
+
+    procedure Check_Consistency (Of_Offices : Office;
+                                 With_Perks : Perks.Goodies);
+
+which would force limited_withs all over the place.  This is telling me
+that this maintenance operation might actually expose shortcomings of
+the original design, and therefore require extensive rearchitecturing.
+
+> Ada with_clauses are too coarse to accurately describe dependencies (unless
+> you restrict yourself to one declaration per package -- which I doubt many
+> people do). I don't see that we can do better (or should try to do better)
+> with 'limited with'.
+
+Ada dependencies are at the level of units (well, declarative parts).
+That has been the case from day 1 and I actually think it would be
+counter-productive to offer finer granularity for type circularity
+(among other things Ada is for programming in the large, and I don't see
+it useful to micro-manage visibility in real-life programs).
+
+...
+> I'd be interested to know Pascal's opinion on this proposal. It seems that
+> he's said that it would be unacceptable, but I'm not certain. Robert's rule
+> would require rechecking all possible dependents [at least to see if they
+> have a limited with] when a with_clause is added, even those that don't
+> directly with the unit. I believe that currently only units that have a
+> with for the changed unit need to be checked, so that potentially would be a
+> significant change.
+
+I didn't reply to Bob E.'s proposal because I don't see how it differs
+from the classic ripple effect that we have been trying to avoid since
+we started discussing 217.  Adding a with_clause to a unit would require
+rechecking all the dependents of that unit to see which ones have a
+limited_with_clause, and in these units locate the constructs that need
+to become illegal (remember that we manage dependencies at the
+declaration level, not at the unit level).
+
+Not only would this entail a considerable implementation effort, it
+would essentially negate incremental compilation.  The basic tenet of
+incremental compilation is that the impact of a change is proportional
+to the size of the change, not to the size of the whole program.  We go
+to considerable lengths to ensure this property.  The analysis needed to
+incrementally detect a dual path would be proportional to the size of
+the whole program, so it's not acceptable.
+
+**************************************************************
+
+From: Robert I. Eachus
+Sent: Tuesday, April 1, 2003  12:59 PM
+
+Ah, but there is a better way to implement my proposal.  I think we can
+agree that the cost of supporting limited withs should be zero if there
+are no limited withs, and the cost of adding a with clause for a unit
+that does not have any limited withs should be small.  To do this, keep
+a database of units with limited withs containing the closure of all
+dependencies for that unit.
+
+If a limited with is added to a unit, there is work to be done.  If a
+with is added to a unit that is in the closure database, you can
+immediately check if it causes an illegality in another unit.  If not
+there is work to be done to extend the closure database with the
+closures of the current unit.  (This can be done at the point the
+context clause and unit name have been processed.)
+
+Also with this approach, units with limited withs but few or no
+dependencies on non-predefined library units have little or no impact on
+compilation times of other units.  I hope that this will be the common
+case for units with limited withs.  There will be many units with units
+with limited withs in their closure, but that is not a problem, it is
+just the closures of units with limited withs themselves that should be
+kept small.
+
+Also note my exclusion of predefined units from the closures.  In a
+heirarchy of units, only levels containing limited withs need this
+closure database.
+
+Oh, as a sort of humorous aside, there isn't much work for a large
+program with lots of limited withs and few real withs.  That is a
+program structure we might want to visit once we have a set of agreed
+rules for limited withs--it may make sense.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Thursday, April 3, 2003  2:31 AM
+
+> If a limited with is added to a unit, there is work to be done.  If a
+> with is added to a unit that is in the closure database, you can
+> immediately check if it causes an illegality in another unit.
+
+There are too many occurrences of the words "with" and "unit" to be
+sure, but I don't think this works.  The pseudo-code for handling the
+situation where "with P" is added to unit Q should look like:
+
+1:    for each unit U that has a limited with loop
+2:        for each unit V which is mentioned by U in a limited_with loop
+3:            if U depends (transitively) on Q and
+4:                P depends (transitively) on V then
+5:                    error;
+6:            end if;
+7:        end loop;
+8:    end loop;
+
+First, notice that the outer loop (line #1) has to process all the units
+that have a limited_with.  If you assume that a constant proportion of
+the units in the program will have limited_with_clauses, this loop runs
+in O(N).  (I'll admit that the proportionality constant may be quite
+small.)
+
+More importantly, to answer the questions at lines #3 and #4 you need to
+traverse the dependencies of units U and P.  The check at line #4 is
+particularly annoying because (1) it has to be in the innermost loop and
+(2) if you want to use a database to speed it up, this database has to
+contain the transitive dependencies of each unit in the program, and
+that means that the size of the database is in O(N**2).
+
+We have customers with tens of thousands of units.  An algorithm with a
+running time in O(N) is unappealing for such large-scale programs.  A
+database of size O(N**2) is just ridiculous.
+
+**************************************************************
+
+From: Robert I. Eachus
+Sent: Thursday, April 3, 2003  6:52 AM
+
+I'll use with P; ... package Q is ... to identify the units involved.
+
+No when you add the with clause, you probe the database, and the initial
+probe takes time on the order of log(N).  If P is not in the database done.
+
+If P is in the database, it may take time proportional to the number of
+units with limited withs that depend on Q to verify whether or not the
+unit mentioned in the with is included in these dependences, but I
+expect that number to be small.  Notice that there is a lot of
+cancelling out that goes on.  A unit has to be in the database only if
+it depends on a unit with a limited with for X, and does not depend on a
+unit with a direct dependence on X.  This is key.  In our canonical
+example, any unit that depends on both Offices and Employees does not
+need to be in the database.  In effect the limited withs cancel out.
+
+If P does appear in the database then you need to update the database to
+add the (limited with) closure of P to the (limited with) closure of Q.
+  This is a join which will take time proportional to the sum of the
+size of the two closures.  In my experience, when the ordinary closures
+get large, the overall project is in trouble, independent of limited
+withs and compiler issues.  If you think of that added with as a bomb
+with effect proportional to the size of the closure you can see what
+happens.      When the average number of side effects of a maintenance
+change is greater than one, any maintenance change has global consequences.
+
+But ignoring that for the moment, the worst case for this step is O(N).
+  And if it is O(N), the time has nothing to do with the limited with.
+You have to compute the closure of Q to insure that it is not circular.
+  The size of the joined closures in the database will be much smaller
+than the one you have to compute anyway, unless all units have limited
+withs.
+
+> More importantly, to answer the questions at lines #3 and #4 you need to
+> traverse the dependencies of units U and P.  The check at line #4 is
+> particularly annoying because (1) it has to be in the innermost loop and
+> (2) if you want to use a database to speed it up, this database has to
+> contain the transitive dependencies of each unit in the program, and
+> that means that the size of the database is in O(N**2).
+>
+> We have customers with tens of thousands of units.  An algorithm with a
+> running time in O(N) is unappealing for such large-scale programs.  A
+> database of size O(N**2) is just ridiculous.
+
+As I said above, well before the database gets that large, the structure
+of the with clauses will be a maintenance nightmare.  But remember that
+constant of proportionality.  Only units that depend on a unit that has
+a limited with, and do not have a direct dependence on the same unit
+need to be in the database.  If 1 in 100 units has a limited with, the
+size of the database would be worst case 1/100 O(N**2).  But even that
+is worst case.  Units with limited withs may be nearer than other units
+to the root of the dependency tree, so lets say that it is ten times
+more likely that a unit will depend on a unit with a limited with.  Now
+the constant of proportionality is 1/1000.  And for programs that don't
+use limited withs, the constant is zero.
+
+And that I think has to be considered the final answer.  If there are no
+units in the library with limited withs, the added effort is at worst
+O(1)--checking to see that there are no limited withs to worry about.
+If a unit does not depend on a unit with limited withs in a library with
+limited withs, the time to determine that is O(logN), where N is the
+number of units with limited withs.  As for a program where a large
+fraction of the units have limited withs, and 100% of the units depend
+on units with limited withs, that structure is going to be costly.  But
+no more costly than a structure where those withs are replaced by withs.
+  (Of course, the structure with the withs would be highly circular, but
+that is beside the point.  We only have to worry about the compile time
+effects of such a program if limited withs are such a wonderful feature
+that "everyone" uses them.)  I fail to see that as an argument against
+the limited with approach.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Thursday, April 3, 2003  9:57 AM
+
+> Notice that there is a lot of
+> canceling out that goes on.  A unit has to be in the database only if
+> it depends on a unit with a limited with for X, and does not depend on a
+> unit with a direct dependence on X.
+
+Now you have completely lost me.  Aren't you proposing that this case be
+illegal?  In a previous message you wrote 'It should be illegal for a
+context to include a  "limited with P;" clause if the remainder of the
+context semantically depends on P.'  So the case you mention is not
+canceling, it's just illegal.
+
+> But remember that constant of proportionality.
+> Only units that depend on a unit that has
+> a limited with, and do not have a direct dependence on the same unit
+> need to be in the database.  If 1 in 100 units has a limited with, the
+> size of the database would be worst case 1/100 O(N**2).
+
+You seem to imply that only the units having limited_with_clauses need to be
+in the database, and I don't understand this.  How do you handle the
+following:
+
+    package P is ... end P;
+
+    with P;
+    package Q is ... end Q;
+
+    -- with Q; -- Uncomment this.
+    package R is ... end R;
+
+    limited with P;
+    with R;
+    package S is ... end S;
+
+My understanding is that you are proposing that uncommenting the "with Q" on
+R would make unit S illegal.  If that's the case, I don't see how you can
+detect this case without storing (or recomputing) the dependencies of Q.
+But then this means that _each_and_every_unit_ needs to be in your database,
+so the proportionality constant is more like 1.  (In essence, I am saying
+that you need pretty much the whole graph to detect the addition of a second
+path, and from an information theory standpoint it doesn't sound too
+surprising.)
+
+**************************************************************
+
+From: Robert I. Eachus
+Sent: Thursday, April 3, 2003  5:03 PM
+
+> Now you have completely lost me.  Aren't you proposing that this case be
+> illegal?  In a previous message you wrote 'It should be illegal for a
+> context to include a  "limited with P;" clause if the remainder of the
+> context semantically depends on P.'  So the case you mention is not
+> canceling, it's just illegal.
+
+The difference is direct and indirect dependence.  All I am proposing is
+that a unit call it Y that depends on a unit X cannot have a limited
+with for X.  You obviously want the body of a unit whose declaration has
+a limited for X to be able to have a regular with for X.  The point is
+that the body of Y, if it has a direct with of X is back in the normal
+Ada universe.  Even though it has a dependence on X and a dependence on
+its declaration which has a limited with for X, you can drop it from the
+database.
+
+> You seem to imply that only the units having limited_with_clauses need to be
+> in the database, and I don't understand this.  How do you handle the
+> following:
+>
+>     package P is ... end P;
+>
+>     with P;
+>     package Q is ... end Q;
+>
+>     -- with Q; -- Uncomment this.
+>     package R is ... end R;
+>
+>     limited with P;
+>     with R;
+>     package S is ... end S;
+>
+> My understanding is that you are proposing that uncommenting the "with Q" on
+> R would make unit S illegal.  If that's the case, I don't see how you can
+> detect this case without storing (or recomputing) the dependencies of Q.
+
+That is the tricky part.  The database needs to contain each unit that
+depends on a units with a limited with Foo, and as mentioned above, does
+not also depend directly or indirectly on Foo.  In this case, when first
+compiling everything without the commented with, the compilation of S
+puts two entries in the database: S --> P, and R --> P.  Since R is in
+the database, recompiling R requires adding its new closure to the
+database:  Q --> P, P --> P (Illegal.)
+
+Only units with limited withs, and units that depend on units with
+limited withs (with the exception explained above) need to be in the
+database.  If a unit declaration has a huge number of with clauses,
+and/or a large list of direct dependences the project (and your
+compiler) have major maintenance problems unrelated to limited withs.
+But for "well structured" Ada programs, bodies often have large
+closures, declarations (I hope the only place we allow limited withs) don't.
+
+In fact, if I were into defining quality measures for Ada code, I would
+probably use the sum of the size of closures of package and generic
+specifications divided by the number of such units as one measure.  If
+you want to add in the size of the closures of bodies, there should be a
+weighting factor that made body closures have one tenth the weight or
+some such multiplier.
+
+> But then this means that _each_and_every_unit_ needs to be in your database,
+> so the proportionality constant is more like 1.  (In essence, I am saying
+> that you need pretty much the whole graph to detect the addition of a second
+> path, and from an information theory standpoint it doesn't sound too
+> surprising.)
+
+As I have said, if a large project with hundreds or thousands of units
+gets to this point, it is already a disaster.  I and others on this list
+can probably tell you horror stories like this.  My favorite was one Air
+Force project where they recompiled the world every night.  (First clue
+of a problem...)
+
+They asked the Air Force for advise on a better compiler, because with
+their current compiler, they were taking over 8 hours to do this and
+were only 20% of the way into the project.  The call got directed to me,
+and I went over the code structure with the developer.  I explained to
+the developers how to structure an Ada program so that key library
+packages didn't have to be recompiled so often.  (Moving with clauses to
+the body where possible, replacing constants in package specs with
+inlined functions and so on.)
+
+About a month later I checked back to see how things were going.  They
+were now doing reference builds once a week--good sign--and recompiling
+the world took less than an hour.  But the key news was that error rates
+were way down and code development was ahead of schedule. ;-)
+
+This is why I take 'problems' of slow compilation with a large grain of
+salt.  If the problem can be traced to bad program structure, I'd rather
+find out about it as soon as possible.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Thursday, April 3, 2003  6:20 AM
+
+Attached is an attempt at updating AI 217-06 based on the recent
+discussion of the visibility rules.  I am not sure that we really need
+to outlaw a use_clause for a limited view of a package.  It seems to me
+that the Beaujolais-ish effect that Tuck originally discovered in this
+area was due to an improper interaction between limited_with_clauses,
+nonlimited_with_clauses, and visibility.  Tuck, what do you think?
+
+[Editor's note: This is version /02 of the AI.]
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Thursday, April 3, 2003  10:50 AM
+
+I think a nice simplification of the implementation is that
+it is *only* expanded names that are affected by a "limited with"
+clause, where the prefix is a package with a limited view.
+Adding "use" clauses to the mix breaks that, and seems like an
+unnecessary complexity.  Also, I believe we are requiring the
+limited "with" itself not mention renamings.  This means that
+it is kept as simple and straightforward as possible.  I might
+go further and disallow uses of renamings of limited with packages,
+rather than just saying they are limited as well.  This would really
+make sure that all uses are clear and unambiguous.
+
+But as far as whether the Beaujolais-ish effect is present,
+I think it is still there if we allow "with P" inside "limited with P.Q;"
+and we allow "use P" after a limited with of P.Q.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Thursday, May 15, 2003  3:29 AM
+
+Attached is a document explaining how we would implement "limited with"
+in our compiler.  This was one of my action items from the last meeting
+(I know, I'm late...).
+
+---
+
+Preliminary Remarks
+
+Because this document is mostly an internal design document, it refers to details of the
+implementation of our compiler that are probably incomprehensible to the uninitiated.
+For the benefit of the ARG readers, I am starting by providing some general information
+on the terminology used below.
+
+Our compilation process is decomposed into three phases: parsing, semantic analysis and
+coding (coding is not particularly relevant to the implementation of limited with clauses).
+At the end of the parsing phase the unit is said to be in the _source_ state, and at the end of
+the semantic analysis it is said to be in the _analyzed_ state.  A unit in the source state has
+a Diana tree with lexical information but no semantic information.  A unit in the analyzed
+state has a Diana tree with all the static semantic information.
+
+The _program_library_ is a cache gathering some of the information found in Diana trees.
+The program library is used to determine which units need to be recompiled without
+having to open numerous Diana trees.
+
+A _decl_#_ is a hash code computed for every declaration in a unit, which describes the
+static semantics of that declaration.  Decl #s serve two purposes:
+
+1 - They are used to build cross-unit reference: a cross-unit reference has the form <unit
+id, decl #>.
+2 - They are used to implement incremental compilation: if a declaration is edited, and its
+decl # changes, then all the declarations that depend on it must be recompiled.
+
+The decl #s existing in a unit are stored in the program library and constitute the _exports_
+of the unit.  Currently, decl #s are computed at the end of semantic analysis.
+
+An _id_table_ is an AVL tree associated with a declarative part that maps an identifier (in
+the lexical sense) to one or more Diana nodes.  Id tables are used for name resolution.
+
+Most of the semantic information related to Diana trees is stored permanently.  However,
+there exists information that is never referenced across compilation units, but needs to be
+recorded on a Diana tree during the course of a single compilation.  This information is
+stored in _temporary_attributes_ of the tree.
+
+I think that's all for the terminology.
+
+
+Implementation Model
+
+In the course of parsing a library package specification, we construct limited decl #s in
+the parser reduction actions.  Limited decl #s are only built for (visible) types and
+package declarations.  They are only based on (1) the type or package name and (2) the
+type's tagged-ness.  These decl #s constitute the limited exports of the unit, and they are
+recorded as such in the program library.  (Meaning that we probably need to run a
+minimal exports collection phase after parsing.)
+
+When a unit is analyzed, full decl #s are allocated for each declaration (as they are today).
+These full decl #s don't replace the limited ones, because there may be clients which
+reference the limited decl #s.  Therefore, we may have two decl #s for a given
+declaration.  This is not a problem when following a pointer, but note that when building
+a reference we must be cautious to use the limited or full decl # depending on whether we
+have visibility on the limited or full view of a unit.
+
+In recompilation terms, consider the situation where a declaration is edited in such a way
+that its full decl # changes, but not its limited decl #.  Only those clients that referenced
+the full decl # need to be recompiled.  This ensures recompilation minimization even in
+the presence of limited withs.
+
+We cannot find ourselves in a situation where the full view of a unit is somehow
+inconsistent with the limited view of the same unit, because as soon as a declaration is
+edited in the Ada editor, it is reparsed, its limited decl # is recomputed, and its full decl #
+is dropped on the floor.  The normal incremental compilation mechanisms then kick in to
+ensure that the proper clients get obsolesced.
+
+I don't foresee any issue with timestamps and the like: after parsing (and limited decl
+numbering) has taken place, a unit looks pretty much as if it had been compiled and then
+edited, so again incremental compilation should save the day.
+
+Also as part of parsing, id tables must be built for each declarative part that is part of the
+limited view.  These limited id tables only contain the names of types and packages.
+They are used for name resolution in clients which only see the limited view of the unit.
+Note that they are not overwritten when the unit is analyzed, because it is possible to
+reference an analyzed unit through a limited with.  So for some Diana nodes we'll have
+two id tables.
+
+At the beginning of the semantic analysis of a unit, the context clauses of that unit and of
+its ancestors are processed.  If a limited with clause is encountered before a nonlimited
+with clause, we records this fact, so that name resolution is later performed using the
+limited id table (we might need a temporary attribute to facilitate this, like we do for
+private with).
+
+When the name of a type is resolved through a limited id table, a temporary attribute is
+set on that type to record the fact that its type spec is effectively incomplete, even though
+it might look like a full type spec in the Diana tree.  This attribute must be consulted
+when checking for premature usages of incomplete types.  (We already have such an
+attribute for checking premature usages of private types, so I expect that this part will
+more-or-less fall out naturally.)
+
+Note that supposedly we do not have to bother with this attribute for types declared in
+other packages (e.g., an access-to-incomplete type declared in an intermediate package).
+Say that such a type was compiled against the limited view of a unit.  If we see the full
+view of that unit, following Diana pointers through the intermediate unit will leads us to
+the full type definition, which is what we need.  If we only see the limited view of the
+original unit, then we should never need to follow any Diana pointer through the
+intermediate unit, because the corresponding source constructs ought to be illegal.  Of
+course, I fully expect that there will be cases where we do too much look-through, but
+these should be fixed, as they probably correspond to know-too-much bugs.
+
+There are some contexts (e.g., use clauses) where the name of a unit referenced through a
+limited with is illegal.  Presumably this is a legality rule, not a name resolution rule, so it
+is checked pretty much like the rules related to private with clauses, i.e., at the point
+where we decorate a name, after name resolution has been performed.
+
+The compilation ordering algorithm must be modified to take limited with relationships
+into account.  Before analyzing a unit, its full closure (i.e., the closure obtained by
+following both limited with clauses and nonlimited with clauses) must be in the source
+state.  Its normal closure (i.e., the one obtained by following only the nonlimited with
+clauses) must be in the analyzed state.  There is no prerequisite for promoting a unit to
+the source state (this is good, it means that you don't do compilation ordering when
+hitting the Syntax button).
+
+When a unit is demoted to source, its full decl #s, full id tables and full export lists are
+deleted, but the limited decl #s, limited id tables and limited export lists must be retained.
+
+The coding phase should be unaffected by all this.  Before a unit is coded, the
+compilation ordering algorithm must ensure that its full closure is analyzed.  This
+guarantees that coding never lands in an unsemanticized unit.
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Thursday, May 15, 2003  8:37 AM
+
+Thanks for doing this.  I guess I must be late too (I forgot about
+this part of the assignment).  Perhaps Randy can do his usual
+excellent job of reminding me of the remaining items on my todo
+list for the upcoming ARG meeting ;-).
+
+As you may have noticed, the AdaUK folks showed a surprisingly
+strong preference for the "type C.T" approach, followed by
+the "limited with."  Since I presented the material, part of
+this might be that my bias showed through, though I tried to
+be impartial (other observers there, such as John Barnes, might
+be able to comment on my success), and frankly, I like the
+"limited with" proposal from a user point of view.
+
+Some of the reasons cited for preferring the type C.T approach were
+that it seemed to be a smaller change that was easier to understand,
+and that it didn't introduce any new kinds of module interdependence.
+It also seemed to be more "structured" to some members of the audience.
+
+For what that's worth...
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, June 17, 2003  2:12 AM
+
+Here is the implementation report I promised at the last meeting for all
+three live AI-217
+proposals. I know that these are really late, but at least you'll have three
+days in which to read them. (Of course, if you're at Ada Europe already,
+that probably is really about 3 minutes. :-(
+
+[Editor's note: The report can be found in the !appendix to AI-217-07.]
+
+**************************************************************
+
+From: Ed Schonberg
+Sent: Thursday, July 10, 2003  12:14 PM
+
+At the last ARG meeting, the following example was discussed:
+
+                     package P is
+                        type T is record ...
+                     end P;
+-----------------------------------------------------------------
+limited with P;                | with P;
+package Q is                   | package R is
+    type Acc_Lim is access P.T;|   procedure Proc (X : P.T);
+    X : Acc_Lim;               | end R;
+end Q;                         |
+-----------------------------------------------------------------
+                      with Q, R;
+                      limited with P;      --   (1)
+                      procedure Main is
+                      begin
+                         R.Proc (Q.X.all); -- Should be legal
+                      end;
+-----------------------------------------------------------------
+
+It was agreed that the call was legal, because the context of the call
+provided the full view of type T, and the explicit dereference, although
+it yielded the limited view, was allowed to "be aware of" the full view.
+Furthermore, the presence or absence of the limited with_clause  (1) did
+not affect the legality of the call.
+
+On the other hand, there was some agreement that, in the same context,
+with the Limited_With present,
+
+                         R.Proc (Q.T'(Q.X.all));
+
+was illegal, because within S, Q.T can only denote the limited view, and
+an incomplete type cannot be the prefix of a qualified expression.
+
+THE rule would seem to be that a direct use of the type name only sees the
+limited view, but uses of the type that come from the semantic closure are
+legal if the non-limited view is available (although the rules will probably
+not mention the term semantic closure).
+
+Consider now the following variation on the previous example:
+
+                     package P is
+                        type T is record ...
+                     end P;
+-----------------------------------------------------------------------------
+limited with P;                | limited with P;            | with P;
+package Q is                   | package R is               | package S is
+    type Acc_Lim is access P.T;|   procedure Proc (X : P.T);|    ...
+    X : Acc_Lim;               | end R;                     | end S;
+end Q;                         |                            |
+-----------------------------------------------------------------------------
+                      with Q, R;
+                      with S;          --  (2)
+                      limited with P;
+                      procedure Main is
+                      begin
+                         R.Proc (Q.X.all); --  legal?
+                      end;
+
+Without the with_clause (2), this should be illegal, because the full view
+of the type is nowhere available (both Q and R have limited_withs on P).
+However, once the with_clause on S is present, the semantic closure does
+make the full view of P available. Following the previous example, this
+would be legal. Either this is counterintuitive (and unpermissibly alcoholic)
+or else the previous attempt at stating the rule is incorrect.
+
+Guidance is welcome. The query comes in connection with a prototype implemen-
+tation of Limited_With that Javier Miranda and I have been constructing within
+GNAT. The implementation so far has been straightforward, and provides the
+desired functionality for all straightforward examples tested so far.  We
+hope that the precise semantics of pathological cases is less of a thicket than
+it appears to us right now!
+
+**************************************************************
+
+From: Gary Dismukes
+Sent: Thursday, July 10, 2003  1:21 PM
+
+> Furthermore, the presence or absence of the limited with_clause  (1) did
+> not affect the legality of the call.
+
+Right, the call is legal because the expected type of the parameter
+is the full view (that's the "context of the call").
+
+> On the other hand, there was some agreement that, in the same context,
+> with the Limited_With present,
+>
+>                          R.Proc (Q.T'(Q.X.all));
+>
+> was illegal, because within S, Q.T can only denote the limited view, and
+> an incomplete type cannot be the prefix of a qualified expression.
+
+My understanding as well (though you mean P.T, not Q.T in the above).
+
+> THE rule would seem to be that a direct use of the type name only sees the
+> limited view, but uses of the type that come from the semantic closure are
+> legal if the non-limited view is available (although the rules will probably
+> not mention the term semantic closure).
+
+I believe that the model we discussed was based on whether the full view
+is available via an expected type, not based on whether the full view
+is in the semantic closure.  If it were based on the semantic closure
+then ripple effects could occur, which we're trying to avoid.
+
+> Consider now the following variation on the previous example:
+> ...
+>                       with Q, R;
+>                       with S;          --  (2)
+>                       limited with P;
+>                       procedure Main is
+>                       begin
+>                          R.Proc (Q.X.all); --  legal?
+>                       end;
+>
+> Without the with_clause (2), this should be illegal, because the full view
+> of the type is nowhere available (both Q and R have limited_withs on P).
+
+Right.
+
+> However, once the with_clause on S is present, the semantic closure does
+> make the full view of P available. Following the previous example, this
+> would be legal. Either this is counterintuitive (and unpermissibly alcoholic)
+> or else the previous attempt at stating the rule is incorrect.
+
+No, the semantic closure shouldn't be used here, only the expected type
+should be taken into account.  At least that was my understanding of
+the model discussed at the meeting.
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Thursday, July 10, 2003  1:21 PM
+
+> THE rule would seem to be that a direct use of the type name only sees the
+> limited view, but uses of the type that come from the semantic closure are
+> legal if the non-limited view is available (although the rules will probably
+> not mention the term semantic closure).
+
+I think the rule is rather that a dereference that delivers an
+incomplete type is allowed so long as it is used in a context
+where the corresponding full type is a) immediately in scope, or
+b) declared within a (non-limited) with'ed package, or c) provided
+by the current complete context of overloading (e.g. as the expected
+type in this example).
+
+Mere presence in the "semantic closure" is *never* sufficient.
+
+> Consider now the following variation on the previous example:
+....[See it above - ED]
+
+The declaration of procedure Proc would only be legal if T were a *tagged*
+type, since only tagged incomplete types may be used as formal parameter types.
+Presuming the example is changed to have T tagged, then...
+
+>                       with Q, R;
+>                       with S;          --  (2)
+>                       limited with P;
+>                       procedure Main is
+>                       begin
+>                          R.Proc (Q.X.all); --  legal?
+>                       end;
+
+The legality is unaffected by the presence of the "with" of S,
+since it doesn't directly contain the declaration of the full type
+(the semantic closure is irrelevant).
+
+Since none of the 3 possibilities I gave above are satisfied, this should
+be considered illegal.  However, I forget whether we allowed for
+a special case for a dereference producing a *tagged* incomplete type.
+We didn't want to allow that for dynamically tagged controlling parameters,
+because those require fetching the tag for dispatching or a tag check.
+I'm not sure what we decided about the case of non-controlling or
+statically-tagged parameters.  If we allow it, then that becomes
+a case (d) to be added to the cases (a)..(c) given above.
+
+...
+
+The key message is presence in the semantic closure is never sufficient.
+All rules must be based on what is directly with'ed, or in the immediate
+scope, or in the overloading context.
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, July 10, 2003  3:16 PM
+
+> Since none of the 3 possibilities I gave above are satisfied, this should
+> be considered illegal.  However, I forget whether we allowed for
+> a special case for a dereference producing a *tagged* incomplete type.
+> We didn't want to allow that for dynamically tagged controlling parameters,
+> because those require fetching the tag for dispatching or a tag check.
+> I'm not sure what we decided about the case of non-controlling or
+> statically-tagged parameters.  If we allow it, then that becomes
+> a case (d) to be added to the cases (a)..(c) given above.
+
+It could be valuable to allow this for class-wide parameters (where there is
+no real dereference, since tagged types are pass-by-reference). The same is
+true of statically bound calls. The important thing is to avoid any
+dereference where there is access to the object itself (as in accessing the
+tag or discriminants), because we don't know enough about the components to
+do anything. It's hard to say how that rule should be written, though.
+
+**************************************************************
+
+From: Ed Schonberg
+Sent: Thursday, July 10, 2003  2:56 PM
+
+The first two cases are clear. The third one (the overloading context) presents
+serious implementation problems, at least for us. Our implementation assumes
+that at any given time in the analysis there is only one view of the type that
+is available. That is either the limited view Tl or the non-limited view Tn.
+When we obtain the expected type from the context, for example the formal of a
+subprogram, there is no indication of the visibility that the type may have
+had at the time the subprogram declaration was analyzed. It's just T, whose
+attributes are either those of Tl or Tn. If the current view is Tl, it is
+possible to indicate that Tn is available (if it showed up in the analysis
+of the closure) but it is never the case that two constituents of an expression
+have different views of the same type. To go back to the first example:
+
+                                 package P is
+                                   type T is tagged record...
+                                 end P;
+
+limited with P;   --  (1)                    with P;   --  (2)
+package Q is                                 package R is
+   type Acc_Lim is access P.T;                  procedure Proc (X : P.T);
+   X : Acc_Lim;                              end R;
+end Q;
+
+                              with Q, R;
+                              limited with P;
+                              procedure Main is
+                              begin
+                                 R.Proc (Q.X.all);
+                              end Main;
+
+By the stated rule this is legal, but it would be illegal if (1) and (2)
+were exchanged (because the context provided by the call would then be
+the limited view, right?).  However, when we analyze Main, these two cases
+are indistinguishable (in our implementation of course, but I thought that
+Janus and Rational had a similar view of things). Therefore, the proposed
+rule does not seem to be implementable for us, without major changes in
+data structures (or a sudden blinding flash of inspiration!).
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Thursday, July 10, 2003  3:30 PM
+
+Perhaps you can treat the incomplete types made available in a limited view
+of a package as truly distinct types that just happen to match
+a particular full type during overload resolution.  Clearly
+you must have rules that allow two different types to match
+under certain circumstances.  For example, T'Class and T are clearly
+different but they match in certain contexts.  Similarly, certain named
+access types can be used in contexts where the expected type
+is an anonymous access type.
+
+Incomplete types can only be used in a few places (e.g. as designated types,
+and if tagged, as formal parameters).  These places seem well enough defined
+that having a special matching rule wouldn't be too bad, presuming you
+can manage to treat them as truly distinct types in most cases.
+
+**************************************************************
+
+From: Robert I. Eachus
+Sent: Friday, July 11, 2003 11:46 AM
+
+I hate it when this happens--but it is just the way my mind works. I
+think/hope that the original case has been addressed. But there is
+another case that looks troublesome:
+
+                     package P is
+                        type T is tagged record ...
+                        procedure Proc (X: T);
+                     end P;
+--------------------------------------------------------------------------------------------
+limited with P;                       | with P;                        |  with P,R;
+package Q is                          | package R is                   |  package body Q is
+    type Acc_Lim is access P.T'Class; |   type Child is new P.T;       |  begin
+    X : Acc_Lim;                      |   procedure Proc (X : Child);  |    X := new Child;
+end Q;                                | end R;                         |  end Q;
+--------------------------------------------------------------------------------------------
+                      with P, Q;
+                      limited with R;
+                      procedure Main is
+                      begin
+                        Proc (Q.X.all); --  which Proc is called?
+                      end;
+
+I think that the "right" answer has to be that R.Proc gets called via
+dispatching.  There is a possibility if I had put the call elsewhere that
+Program_Error could occur, but that is nothing new.  I don't think there are
+any cases where type T could be private and only visible through a limited
+with, and the access type is visible through a with.
+
+***************************************************************
+
+From: Tucker Taft
+Sent: Friday, July 11, 2003 11:46 AM
+
+I don't know what the issue is here.  package body Q is illegal because
+it isn't needed by its spec, but presumably you add a pragma Elaborate_Body
+or some sort of dummy procedure which will cause it to be allowed,
+it seems clear that by the time you get to Main, Q.X points at an object
+with tag R.Child (you need to add a "use" for R in the body of Q as well).
+In general, whether you use limited with or with has no run-time effect,
+except perhaps elaboration order, so what exactly is your question?
+
+***************************************************************
+
+From: Robert I. Eachus
+Sent: Saturday, July 12, 2003  6:32 PM
+
+>I don't know what the issue is here.  package body Q is illegal because
+>it isn't needed by its spec, but presumably you add a pragma Elaborate_Body
+>or some sort of dummy procedure which will cause it to be allowed,
+
+Oops, consider it done.
+
+>it seems clear that by the time you get to Main, Q.X points at an object
+>with tag R.Child (you need to add a "use" for R in the body of Q as well).
+
+Just to make sure we are on the same wavelength, assume I change the body of Q to:
+with P,R;
+package body Q is
+begin
+X := new R.Child;
+end Q;
+
+to fix that.
+
+>In general, whether you use limited with or with has no run-time effect,
+>except perhaps elaboration order, so what exactly is your question?
+
+Sorry if that wasn't clear. It is possible for a limited with to result
+in a (run-time) elaboration order that results in additional ABE checks
+being necessary. I think I have convinced myself that these are already
+language defined checks, but that get optimized away currently.
+
+***************************************************************
+
+
 

Questions? Ask the ACAA Technical Agent