CVS difference for ais/ai-40217.txt

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

--- ais/ai-40217.txt	2003/03/22 04:18:07	1.4
+++ ais/ai-40217.txt	2003/08/08 01:44:10	1.5
@@ -7712,7 +7712,7 @@
 
 **************************************************************
 
-From: Tucker Taft
+From: Randy Brukardt
 Sent: Monday, February 3, 2003  8:16 PM
 
 Tucker replied to me:
@@ -7790,9 +7790,1313 @@
 
 **************************************************************
 
+From: Randy Brukardt
+Sent: Friday, March 21, 2003  10:40 PM
+
+
+Here is an updated type stubs AI. What's new is essentially what was
+discussed at Padua:
+
+-- The context clause has been changed to "limited with". I looked for other
+syntax, but this seems the best. I considered using less-preferable syntax
+in order to avoid confusion with other proposals, but that seems to be a
+mistake. After all, soon there will be only one proposal, and that proposal
+should use the best possible syntax.
+
+-- There are two new post-compilation rules. The first is simply that the
+unit named in a "limited with" is needed in the partition. That's necessary
+so that the other rules can be enforced. The second is that the unit which
+has a "limited with" clause in its context_clause must be in the semantic
+closure of the unit named in the "limited with" clause. This rule insures
+that the completing type "knows" about any type_stubs that it has. This
+means that all checking of the legality of a completion can occur when the
+unit containing the completion is compiled. In addition, the implementation
+can know that incomplete types of the type exist, and adjust its choice of
+representations accordingly (that was considered important in Padua).
+
+-- Only a single stub is allowed for each incomplete type. (This eliminates
+the need to
+match different stubs, and was considered important in Padua. Given the
+"incomplete view" model that I've adopted, there is no longer any wording
+needed for this case at all, but the restriction has been retained as it may
+simplify implementations. This is dicussed in the !discussion section of the
+AI.)
+
+-- The full type name is specified in the type stub, thus allowing the name
+to be changed if necessary (this provides a direct solution to the "Object"
+problem).
+
+-- I defined "incomplete view" and "complete view", and avoided futzing with
+the visibility rules at all. The basic rule is that if the complete view is
+available, it is used instead of the incomplete view. See the AI for
+details.
+
+-- I didn't try to allow local and nested completion of type stubs. That's
+relatively easy to do, but it makes the wording complicated in a couple of
+places. If we went further and allowed completion in private parts and
+bodies (presumably subject to some restrictions), then an existing
+incomplete types would be just a shorthand for a type stub.
+
+I'll now go and try to relax before the inevitable barrage of problems...
+
+[Editor's note: This is version /02 of the AI.]
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Friday, March 21, 2003  11:48 PM
+
+I've refreshed this example I've used in the past. I'll send versions using
+alternative #6 and #7 momentarily.
+
+----
+
+This example shows two ways that I would use alternative #5 of AI-217
+in the Claw Builder.
+
+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;
+
+
+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.
+(Caveat, I haven't actually done this, not having a compiler with this
+feature.) Using alternative #5 (and assuming that AI-326 is approved), this
+could look like:
+
+   limited with CBuild_Root;
+   package CBuild_Root_Abstract is
+      type Root_Window_Type is tagged
+          separate of CBuild_Root.Root_Window_Type;
+      type Any_Window_Access_Type is access all 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.
+
+In order to keep the access types compatible, the real package would be
+modified to:
+
+   with CBuild_Root_Abstract; -- Note: Required by alternative #5/02
+   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;
+
+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 Root_Window_Type is tagged separate of
+          CBuild_Root_Definition.Root_Window_Type;
+      type Any_Window_Access_Type is access all Root_Window_Type'Class;
+
+      procedure Show (Window : in out Root_Window_Type'Class);
+      procedure Hide (Window : in out Root_Window_Type'Class);
+      function Display_Name (Window : in Root_Window_Type'Class)
+          return String;
+      ...
+   end CBuild_Root;
+
+The "creator" package would be as in the previous example (except for the
+name):
+
+   with CBuild_Root; -- Note: Required by alternative #5/02
+   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_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_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 Root_Window_Type'Class) is
+      begin
+          CBuild_Root_Definition.Show (Window);
+      end Show;
+      procedure Hide (Window : in out Root_Window_Type'Class) is
+      begin
+          CBuild_Root_Definition.Hide (Window);
+      end Hide;
+      function Display_Name (Window : in 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.
+
+For instance, the menu case would look something like:
+
+  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;
+
+The dereference in the call to Show is allowed, by the second bulleted rule
+under when a dereference is allowed. This is OK and can be implemented
+because we don't need to know anything at all about the real type in order
+to generate the call. Such a call cannot be dispatching (the only way to see
+a primitive operation is for the completion to be "available"). Thus, it
+cannot be using a tag. And we know the parameter passing mode (by
+reference), and we know that the body (or at least some body) must be in the
+scope of the
+completion, or nothing at all must be done with the type.
+
+---
+
+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 Root_Window_Type is
+       tagged separate of CBuild_Root.Root_Window_Type;
+    type Menu_Item is record
+       Name : String (1..20);
+       Action : Action_Type;
+       Dialog : access 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.
+
+However, this solution runs afoul of the only one stub rule. If there is
+more than one package that needs a stub, we're forced to switch back to one
+of the other structures. Since that rule buys a bit of implementation
+simplification and not much else (it has no effect on the wording
+currently), it may make sense to drop it.
+
+Another issue is the requirement that the package containing the completing
+type have semantic dependence on the stub-containing package. In some cases,
+that will reintroduce the circularity that we're trying to eliminate. In
+those cases, two packages are required.
+
+That concludes my look at using alternative #5/02 in CBuild. Coming soon: a
+similar look at alternative #7.
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, March 19, 2003 10:17 PM
+
+I'm trying to get a handle on the (detailed) type rules of Ada in order to
+make a solid attempt at making sense out of the availability rules. I'm
+writing this as stream-of-consciousness, so I don't know how useful it will
+be to the ARG in general, and I may never actually reach a conclusion. But
+at least Tucker and Pascal ought to read it, and point out where it goes
+wrong (if it goes wrong).
+
+I'm essentially immediately stuck, because types do not have names, and
+definitely do not follow the visibility rules. It appears that they always
+exist. (Practically, they require semantic closure, but that's really an
+implementation issue.) But I can't find anything in the standard that says
+that.
+
+If that wasn't true, then the classic example:
+
+    package A is
+       type Foo is range 1 .. 10;
+    end A;
+
+    with A;
+    package B is
+       V1, V2 : Foo := 1;
+    end B;
+
+    with B;
+    procedure C is
+    begin
+       B.V1 := B.V2; -- Foo is not visible here.
+    end C;
+
+would be illegal. But it clearly is not.
+
+OTOH, the properties of a type are controlled by visibility. That is, which
+view of a type is used is controlled by visibility:
+
+    package D is
+        type P is private;
+        Con : constant P;
+    private
+        type P is new Integer;
+        Con : constant P := 1;
+    end D;
+
+    package D.Child is
+        type Bar1 range 0 .. Con; -- Illegal, full view not visible (so not
+integer type).
+    private
+        type Bar2 range 0 .. Con; -- Legal, full view visible.
+    end D.Child;
+
+While I can't find the actual rules that make this so, this IS the way
+things work. (Are you with me so far??) [I chose type declarations here,
+because it is one of very few places where this is a resolution rather than
+legality rule. If only legality rules are involved, this is clearly easier.]
+
+As a practical matter, the types that exist are those in the semantic
+closure. That's simply because compilers can't have every type that might
+exist in their symbol table, and other rules of the language insure that
+types not in the semantic closure can't be used in any way.
+
+The important point here is that the name of a type has absolutely no
+relevance to its usability.
+
+Now, in both child type stubs (type C.T) and in the type stubs that I'm
+working on, if the completion is in the semantic closure, then the stub also
+must be in the closure. (I don't believe that this is true for Limited With,
+which may make the problem harder; thankfully I don't have to solve that
+problem.)
+
+Let's assume that the stub and completion are views of the same type. That
+seems like the easiest model to work from, as it is similar to the models
+for private types and existing incomplete types.  (This has NOTHING to do
+with the names of the stub and completion. I've said nothing about names,
+and don't expect to ever in this discussion. After all, only subtypes have
+names, and a subtype is not a type. Reread 3.2 & 3.2.1 if necessary. :-)
+
+Clearly, in any case of interest, the type has to be in the semantic closure
+(the stub and completion are the same type). Otherwise, no object could
+exist, and there is nothing that we could do. So we're only interested in
+what rules we need concerning the properties of the type (which allows us to
+bring in visibility if we need to).
+
+It's also clear, that if the completion of the type is not in the semantic
+closure, we can only have incomplete type properties.
+
+The natural rule is that if the completion of the type is in the semantic
+closure, then the properties of the complete type can be used. That allows
+the examples that we want to work to work without any handstands. However,
+this has a nasty ripple effect, where the addition or deletion of a context
+clause on a unit can change the legality of a distant unit. Besides making
+incremental compilation impossible (giving Rational heartburn), this is very
+bad for maintenance and modularity of code.
+
+This leads to my asking why we don't have this problem in Ada 95 as it is.
+The answer appears to be that the rules of the language were carefully
+constructed to prevent ever 'exporting' a  more capable view into a unit
+that has less visibility. That is, the only places where a more capable view
+can be used is where it is 'naturally' available; subtyping and renames
+can't change that. For instance, the full view of a private type cannot be
+subtyped in the visible part of a non-private child. And the private part of
+a renamed package remains private.
+
+Of course, this brings up the question of whether some rules would have the
+same effect for type stubs (and its relatives). In order to accomplish that,
+we'd pretty much have to ban any use of the completing type to declare
+objects or components outside of that package. That pretty much would
+eliminate the intended use of the feature.
+
+But its important to realize that the visibility of a type appears to depend
+on where it is originally declared. We're not taking about visibility of
+names (which of course can be subtyped and/or renamed), but of the type
+itself. Since types never have names, the only thing that has visibility
+that we could be talking about is the declaration itself (as that's what 8.3
+talks about).
+
+This distinction is irrelevant for private types (and original incomplete
+types), because the places that have visibility on the full declaration are
+the only ones that can use the full view. So the visibility of the name is
+the same as the visibility of the type. Any renames/subtypes have the same
+visibility as the original type (you don't get to look in the private part
+of a rename just because its a rename).
+
+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. This does have the unfortunate effect
+that library-level renames aren't good enough for this purpose, but perhaps
+a special rule to allow them would be worthwhile.
+
+In particular, it is not necessary to exclude subtypes or renames, because
+they have no impact on the visibility of the type (as opposed to the
+visibility of some subtype of the type).
+
+This means that Tucker's original wording is correct, but that the meaning
+is essentially what his e-mail attempts at wording say. He's just hung up on
+the name of a type, which is completely irrelevant (since types don't have
+names).
+
+Since only the visibility of the original declaration (or library-level
+renaming of the original declaration's package) matter, no ripple effects
+are possible. No with, no complete type operations.
+
+'Extra' availablility (as in the assignment of two objects) is always
+available (as the type always exists, at least in theory). Since that is the
+case, there is no ripple effects possible.
+
+This brings up the question of whether the requirement that the completion
+'see' the stub is really necessary. It doesn't seem to be necessary for the
+purpose of availability rules.
+
+We do need such a rule by the discussion of Padua question #1: "Does the
+completion know about incomplete type? (This is an implementation issue.)
+Some implementations need to know whether there are any incomplete types
+around. That may change the choice of representations for access types, etc.
+This should be yes; but an implementation can handle this with contortions
+or we could add an Implementation Permission. The group feels that this is
+important enough to some implementations that we have to require it."
+
+I don't quite understand the issue here. It seems that the incomplete type
+might want to know the full type for that purpose, but that isn't possible
+in general (with any mutually dependent type solution). I don't see much
+advantage in knowing the reverse, unless the compiler just wants to use
+"assume-the-worst" everywhere in that case.
+
+I think that's it.
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Thursday, March 20, 2003  1:48 PM
+
+Randy Brukardt wrote:
+>
+> I'm trying to get a handle on the (detailed) type rules of Ada in order to
+> make a solid attempt at making sense out of the availability rules. I'm
+> writing this as stream-of-consciousness, so I don't know how useful it will
+> be to the ARG in general, and I may never actually reach a conclusion. But
+> at least Tucker and Pascal ought to read it, and point out where it goes
+> wrong (if it goes wrong).
+>
+> I'm essentially immediately stuck, because types do not have names, and
+> definitely do not follow the visibility rules. It appears that they always
+> exist. (Practically, they require semantic closure, but that's really an
+> implementation issue.) But I can't find anything in the standard that says
+> that.
+
+Types don't "always exist."  They exist between their elaboration
+and the end of the lifetime of their scope.  For library-level types,
+that means pretty much "forever."  I suspect though you are talking
+about compile-time legality.  In that case, what generally matters
+is "scope" rather than visibility.  Scope for declarations
+is generally transitive whereas visibility isn't (when dealing with "with"
+clauses, that is).
+
+> If that wasn't true, then the classic example:
+>
+>     package A is
+>        type Foo is range 1 .. 10;
+>     end A;
+>
+>     with A;
+>     package B is
+>        V1, V2 : Foo := 1;
+>     end B;
+>
+>     with B;
+>     procedure C is
+>     begin
+>        B.V1 := B.V2; -- Foo is not visible here.
+
+But Foo is "in scope".
+
+>     end C;
+>
+> would be illegal. But it clearly is not.
+
+"Foo" is in scope.
+
+>
+> OTOH, the properties of a type are controlled by visibility. That is, which
+> view of a type is used is controlled by visibility:
+
+No, I think this is mostly "scope" based rather than "visibility" based,
+though when two declarations in scope, what matters is which one
+is "hidden from all visibility."  Perhaps "hidden from all visibility" ought
+to be renamed "temporarily not in scope."
+
+>     package D is
+>         type P is private;
+>         Con : constant P;
+>     private
+>         type P is new Integer;
+>         Con : constant P := 1;
+>     end D;
+>
+>     package D.Child is
+>         type Bar1 range 0 .. Con; -- Illegal, full view not visible (so not
+> integer type).
+>     private
+>         type Bar2 range 0 .. Con; -- Legal, full view visible.
+>     end D.Child;
+>
+> While I can't find the actual rules that make this so, this IS the way
+> things work. (Are you with me so far??) [I chose type declarations here,
+> because it is one of very few places where this is a resolution rather than
+> legality rule. If only legality rules are involved, this is clearly easier.]
+>
+> As a practical matter, the types that exist are those in the semantic
+> closure. That's simply because compilers can't have every type that might
+> exist in their symbol table, and other rules of the language insure that
+> types not in the semantic closure can't be used in any way.
+
+Because they are out of scope.
+
+>
+> The important point here is that the name of a type has absolutely no
+> relevance to its usability.
+
+I'm not sure what you mean by that.  The actual identifier used is
+not particularly relevant.  But the location of its declaration
+is highly relevant, because only within the scope of that
+declaration can you "use" the type.  The tricky part is when
+there are two (or more) declarations that provide different
+views of the "same" type.  The location of those two declarations
+is highly relevant to a given use of the type.  If only one is
+in scope, that that one clearly determines what happens.  When
+both are in scope, then we have to presume that one "trumps" the
+other.  According to 8.3(19) a completion, if in scope, "trumps"
+the declaration it completes.  However, with the various AI-217
+proposals, that may be too simplistic, since scopes are transitive
+through "with" clauses.  I claim that we should adjust 8.3(19) to
+make it work the way we want for whatever AI-217 proposal we adopt.
+I suspect we will want to have the completion "trump" the original
+declaration only when it is visible, and perhaps only when the
+enclosing library package declaration, or a library unit renaming
+thereof, is visible.
+
+>
+> Now, in both child type stubs (type C.T) and in the type stubs that I'm
+> working on, if the completion is in the semantic closure, then the stub also
+> must be in the closure. (I don't believe that this is true for Limited With,
+> which may make the problem harder; thankfully I don't have to solve that
+> problem.)
+>
+> Let's assume that the stub and completion are views of the same type. That
+> seems like the easiest model to work from, as it is similar to the models
+> for private types and existing incomplete types.  (This has NOTHING to do
+> with the names of the stub and completion. I've said nothing about names,
+> and don't expect to ever in this discussion. After all, only subtypes have
+> names, and a subtype is not a type. Reread 3.2 & 3.2.1 if necessary. :-)
+
+Perhaps the identifiers are not important, but the location of the *declarations*
+is important, both to scope and to the rules for "hidden from all visibility."
+One of the problems is that in the existing RM, we don't explicitly deal
+with the problem that when you dereference a type that when declared,
+was access-to-incomplete, it "magically" becomes access-to-complete in
+certain locations.  I claim those are exactly the places where the incomplete
+type declaration is hidden from all visibility according to 8.3(19), but
+I don't see any explicit words to that effect.  It seems like 4.1(9) should
+probably talk about this more explicitly.  We might be able to leave 8.3(19)
+the way it is, and just add words to 4.1(9) to control when we want ".all"
+to be of the compete type rather than the incomplete type.
+
+Similarly, we could beef up 3.10.1(5-10) to identify what happens when you
+have a name that "denotes" an incomplete type declaration -- whether it
+is illegal (because the complete type and/or its enclosing package is visible,
+say) or whether it in fact denotes the complete type.
+
+...
+> We do need such a rule by the discussion of Padua question #1: "Does the
+> completion know about incomplete type? (This is an implementation issue.)
+> Some implementations need to know whether there are any incomplete types
+> around. That may change the choice of representations for access types, etc.
+> This should be yes; but an implementation can handle this with contortions
+> or we could add an Implementation Permission. The group feels that this is
+> important enough to some implementations that we have to require it."
+>
+> I don't quite understand the issue here. It seems that the incomplete type
+> might want to know the full type for that purpose, but that isn't possible
+> in general (with any mutually dependent type solution). I don't see much
+> advantage in knowing the reverse, unless the compiler just wants to use
+> "assume-the-worst" everywhere in that case.
+
+It is quite helpful in implementations that sometimes use fat pointers
+to unconstrained array subtypes to know whether there are any incomplete
+views that exist.  Or more precisely, it is helpful to know there might
+exist access-to-incomplete types that are *not* aware that the full type is an unconstrained
+array.  If the full type can always "see" the incomplete type declaration,
+then it is aware that the incomplete type exists, and whether access-to-incomplete
+types might be declared, so it can arrange that the fat pointer is *never*
+used for access types to this type.
+
+>
+> I think that's it.
+
+I pretty much agree with your analysis.  I maintain that 8.3(19) is
+still the critical issue, and its implicit connection with 4.1(9) and
+3.10.1(5).  We might want at least to make more explicit the connection between
+"hidden from all visibility" and the designated type mentioned in 4.1(9).
+Since 3.10.1(5) uses the term "denotes" it is clearly linked to visibility.
+
+I suppose a different place to "fix" 4.1(9) and 3.10.1(5) is 8.6(16-18)
+where it talks about denoting a declaration vs. denoting a view.
+These 3 paragraphs are talking about the "current instance" stuff, but
+could perhaps also deal with incomplete/complete view decisions.
+
+And let's not forget 8.6(20-25) where we want to add our extended
+matching rules between complete and incomplete views, though
+I think that is a pretty independent problem, and needn't be
+burdened with ripple-effect concerns.
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 20, 2003  4:59 PM
+
+Tucker replied to my stream-of-consciousness:
+...
+
+> Types don't "always exist."  They exist between their elaboration
+> and the end of the lifetime of their scope.  For library-level types,
+> that means pretty much "forever."  I suspect though you are talking
+> about compile-time legality.  In that case, what generally matters
+> is "scope" rather than visibility.  Scope for declarations
+> is generally transitive whereas visibility isn't (when dealing with "with"
+> clauses, that is).
+
+OK. I was thinking that this morning, anyway.
+
+> > OTOH, the properties of a type are controlled by visibility. That is,
+which
+> > view of a type is used is controlled by visibility:
+>
+> No, I think this is mostly "scope" based rather than "visibility" based,
+> though when two declarations in scope, what matters is which one
+> is "hidden from all visibility."  Perhaps "hidden from all visibility"
+ought
+> to be renamed "temporarily not in scope."
+
+That's confusing (if right). The "partial view" and the "full view" of a
+private type are the same type, just different views. Similarly (or at
+least, it ought to be similarly!) the "incomplete view" and "complete view"
+are different views of the same type.
+
+Conceptually, it makes more sense to talk about when the properties of a
+particular view are available rather than to talk about when the "lesser" of
+two views is hidden.
+
+(Which reminds me of a issue that Pascal worried about: the three view type.
+That's not a problem if you look at a type's different views having
+increasing capability. At least as long as the different more restricted
+views have properties which are a strict subset of the less restricted
+view.)
+
+I don't suppose it actually matters in practice. What worries me about
+talking about hiding something is that if you get it wrong, you've got two
+things sitting around, and confusion. If you talk about capabilities, the
+worst that happens is you have less capability than you ought to.
+
+> > The important point here is that the name of a type has absolutely no
+> > relevance to its usability.
+>
+> I'm not sure what you mean by that.  The actual identifier used is
+> not particularly relevant.  But the location of its declaration
+> is highly relevant, because only within the scope of that
+> declaration can you "use" the type. The tricky part is when
+> there are two (or more) declarations that provide different
+> views of the "same" type.  The location of those two declarations
+> is highly relevant to a given use of the type.  If only one is
+> in scope, that that one clearly determines what happens.  When
+> both are in scope, then we have to presume that one "trumps" the
+> other.  According to 8.3(19) a completion, if in scope, "trumps"
+> the declaration it completes.  However, with the various AI-217
+> proposals, that may be too simplistic, since scopes are transitive
+> through "with" clauses.  I claim that we should adjust 8.3(19) to
+> make it work the way we want for whatever AI-217 proposal we adopt.
+> I suspect we will want to have the completion "trump" the original
+> declaration only when it is visible, and perhaps only when the
+> enclosing library package declaration, or a library unit renaming
+> thereof, is visible.
+
+Right. It's the location of the declaration, not the name. And, since
+renamings and subtyping can't change the location of the declaration, only
+the name, they don't matter.
+
+And, I think I've come around to your "fix 8.3(19)" position. (It only took
+two months. :-)
+
+...
+> One of the problems is that in the existing RM, we don't explicitly deal
+> with the problem that when you dereference a type that when declared,
+> was access-to-incomplete, it "magically" becomes access-to-complete in
+> certain locations.  I claim those are exactly the places where the
+incomplete
+> type declaration is hidden from all visibility according to 8.3(19), but
+> I don't see any explicit words to that effect.  It seems like 4.1(9)
+should
+> probably talk about this more explicitly.  We might be able to leave
+8.3(19)
+> the way it is, and just add words to 4.1(9) to control when we want ".all"
+> to be of the compete type rather than the incomplete type.
+
+Humm.
+
+> Similarly, we could beef up 3.10.1(5-10) to identify what happens when you
+> have a name that "denotes" an incomplete type declaration -- whether it
+> is illegal (because the complete type and/or its enclosing package is
+visible,
+> say) or whether it in fact denotes the complete type.
+
+I think that's what we did in the earlier type stubs.
+
+If you believe the model that an incomplete type and the completing type are
+just views of the same type, then the existing 3.10.1(10) only needs a minor
+tweak:
+
+    A dereference (whether implicit or explicit - see 4.1) shall not be of
+an incomplete view.
+
+(And we'd have to define "incomplete view" somewhere.)
+
+
+...
+> > I don't quite understand the issue here. It seems that the incomplete
+type
+> > might want to know the full type for that purpose, but that isn't
+possible
+> > in general (with any mutually dependent type solution). I don't see much
+> > advantage in knowing the reverse, unless the compiler just wants to use
+> > "assume-the-worst" everywhere in that case.
+>
+> It is quite helpful in implementations that sometimes use fat pointers
+> to unconstrained array subtypes to know whether there are any incomplete
+> views that exist.  Or more precisely, it is helpful to know there might
+> exist access-to-incomplete types that are *not* aware that the full type
+> is an unconstrained array.  If the full type can always "see" the
+incomplete
+> type declaration, then it is aware that the incomplete type exists, and
+whether
+> access-to-incomplete types might be declared, so it can arrange that the
+fat
+> pointer is *never* used for access types to this type.
+
+OK, that's what I meant by assume-the-worst.
+
+Anyway, the question is moot, because I found a much better reason for the
+requirement. With the requirement, we can make all of the checks for
+'correct' completion when we see the completing type. There is no need to do
+those at some place where the two types intersect. That's enough of a
+simplification in implementation (if not in the words) and in understanding
+to make it worth the rule. That fact that it helps implementations as well
+is a bonus.
+
+> I pretty much agree with your analysis.  I maintain that 8.3(19) is
+> still the critical issue, and its implicit connection with 4.1(9) and
+> 3.10.1(5).  We might want at least to make more explicit the connection
+between
+> "hidden from all visibility" and the designated type mentioned in 4.1(9).
+> Since 3.10.1(5) uses the term "denotes" it is clearly linked to
+visibility.
+
+I'd suggest defining "incomplete view" similarly to 7.3(15); then 4.1(9) can
+be left alone. Adjustments to 8.3(19) are needed to determine which view is
+being used. (I'm presuming that the wording for this for private types is OK
+and can be borrowed where necessary.) Also, by using "view" here, the
+intersection of the rules for incomplete and for private (which happens if
+we allow completion by a private type) shouldn't give trouble. 3.10.1(5)
+would then talk about denoting an incomplete view.
+
+> I suppose a different place to "fix" 4.1(9) and 3.10.1(5) is 8.6(16-18)
+> where it talks about denoting a declaration vs. denoting a view.
+> These 3 paragraphs are talking about the "current instance" stuff, but
+> could perhaps also deal with incomplete/complete view decisions.
+
+I think I'd rather piggyback on the partial view/full view rules we already
+have. That should make Pascal more conformable with multiple view types, as
+the model would be unified.
+
+> And let's not forget 8.6(20-25) where we want to add our extended
+> matching rules between complete and incomplete views, though
+> I think that is a pretty independent problem, and needn't be
+> burdened with ripple-effect concerns.
+
+There's nothing to extend if they are two views of the same type - we get
+'matching' for free. We can use legality rules to get rid of any cases that
+we don't want (there don't seem to be many of those!).
+
+Where I got stuck was that the dereferencing rules talk about "covering the
+completion". Since it's just a view of the same type, that's a meaningless
+statement.
+
 **************************************************************
 
+From: Tucker Taft
+Sent: Thursday, March 20, 2003  9:57 PM
+
+Randy Brukardt wrote:
+...
+> That's confusing (if right). The "partial view" and the "full view" of a
+> private type are the same type, just different views. Similarly (or at
+> least, it ought to be similarly!) the "incomplete view" and "complete view"
+> are different views of the same type.
+>
+> Conceptually, it makes more sense to talk about when the properties of a
+> particular view are available rather than to talk about when the "lesser" of
+> two views is hidden.
+
+I'm not sure what is the significant difference,
+but whatever...
+
+>
+> (Which reminds me of a issue that Pascal worried about: the three view type.
+> That's not a problem if you look at a type's different views having
+> increasing capability. At least as long as the different more restricted
+> views have properties which are a strict subset of the less restricted
+> view.)
+
+Actually, we must remember that there
+can be multiple "views" of the same type (7.3.1(3-4)),
+because the properties can be revealed incrementally.
+A type might initially appear limited, because one of
+its components is limited private.  Then it may turn out
+that the full type of the component is non-limited, causing
+the enclosing type to become nonlimited.  Similarly,
+an array might initially be an array-of-private, and
+then turn out to be an array-of-boolean, picking up
+"and" and "or", etc.
+
+>
+> I don't suppose it actually matters in practice. What worries me about
+> talking about hiding something is that if you get it wrong, you've got two
+> things sitting around, and confusion. If you talk about capabilities, the
+> worst that happens is you have less capability than you ought to.
+
+I'm not sure why one of these is worse than the other.
+
+
+> ...
+>
+> If you believe the model that an incomplete type and the completing type are
+> just views of the same type, then the existing 3.10.1(10) only needs a minor
+> tweak:
+>
+>     A dereference (whether implicit or explicit - see 4.1) shall not be of
+> an incomplete view.
+>
+> (And we'd have to define "incomplete view" somewhere.)
+
+But I thought our extended matching rules would
+change this, so that dereference *could* be
+incomplete, so long as they are matched against
+something that is complete.
+
+> ...
+>>And let's not forget 8.6(20-25) where we want to add our extended
+>>matching rules between complete and incomplete views, though
+>>I think that is a pretty independent problem, and needn't be
+>>burdened with ripple-effect concerns.
+>
+>
+> There's nothing to extend if they are two views of the same type - we get
+> 'matching' for free. We can use legality rules to get rid of any cases that
+> we don't want (there don't seem to be many of those!).
+
+Hmmm... I'm not sure that works, since 8.6 talks about
+properties of the type (e.g. being an access type, or
+being covered by some class-wide type).
+Presumably those are properties of the "view" --
+a dereference of an access-to-incomplete is presumably
+an incomplete view, so it would not be known whether
+it was an access type, or whether it was covered by
+some class-wide type (unless the class-wide type were
+the same-incomplete-type'Class).
+
+> Where I got stuck was that the dereferencing rules talk about "covering the
+> completion". Since it's just a view of the same type, that's a meaningless
+> statement.
+
+I don't quite agree.  When you have an incomplete view,
+you don't know whether it is covered by some arbitrary
+class-wide type.  You need to "consult" the completion
+to know that.  We need to decide when you are allowed
+to consult the completion.  I have a feeling we are perhaps
+being a bit too generous already.
+
 **************************************************************
+
+From: Randy Brukardt
+Sent: Friday, March 21, 2003  6:39 PM
+
+> > I don't suppose it actually matters in practice. What worries me about
+> > talking about hiding something is that if you get it wrong, you've got two
+> > things sitting around, and confusion. If you talk about capabilities, the
+> > worst that happens is you have less capability than you ought to.
+>
+> I'm not sure why one of these is worse than the other.
+
+Because in the second case, things are well-defined (you have less
+capability). In the first case, you have two views of the same thing visible
+simultaneously, and there is nothing in the language to say how that gets
+resolved. It means immediate work for the ARG; in the second case, the ARG
+only has to work if the missing capability is actually important (and that's
+rare).
+
+> > ...
+> >
+> > If you believe the model that an incomplete type and the completing type are
+> > just views of the same type, then the existing 3.10.1(10) only needs a minor
+> > tweak:
+> >
+> >     A dereference (whether implicit or explicit - see 4.1) shall not be of
+> > an incomplete view.
+> >
+> > (And we'd have to define "incomplete view" somewhere.)
+>
+> But I thought our extended matching rules would
+> change this, so that dereference *could* be
+> incomplete, so long as they are matched against
+> something that is complete.
+
+Those aren't matching rules. I'm very against context-specific type
+matching, because it's conceptually ugly (what happens depends on context)
+and because we use a single routine to do all type matching, based solely on
+the type ids (which always exist in our compilers; they don't have any
+scoping/visibility themselves).
+
+Anyway, the rules as written in AI-00217-04 only talk about when a
+dereference is legal; it has nothing to do with "type matching". There are
+just some additional cases where a dereference of an incomplete type is
+legal. And yes, I do mean to have those described at this point in the text.
+
+I note that the AI-00217-07 that you submitted has precisely the same
+legality rules; there is no change to 8.6 and certainly no extension of type
+matching.
+
+> ...
+> > There's nothing to extend if they are two views of the same type - we get
+> > 'matching' for free. We can use legality rules to get rid of any cases that
+> > we don't want (there don't seem to be many of those!).
+>
+> Hmmm... I'm not sure that works, since 8.6 talks about
+> properties of the type (e.g. being an access type, or
+> being covered by some class-wide type).
+> Presumably those are properties of the "view" --
+> a dereference of an access-to-incomplete is presumably
+> an incomplete view, so it would not be known whether
+> it was an access type, or whether it was covered by
+> some class-wide type (unless the class-wide type were
+> the same-incomplete-type'Class).
+
+The anonymous access case is irrelevant; an incomplete type cannot be
+completed by an anonymous type (we got rid of named anonymous access types,
+thank heaven). And access-to-incomplete of course is covered by the existing
+rule.
+
+> > Where I got stuck was that the dereferencing rules talk about "covering the
+> > completion". Since it's just a view of the same type, that's a meaningless
+> > statement.
+>
+> I don't quite agree.  When you have an incomplete view,
+> you don't know whether it is covered by some arbitrary
+> class-wide type.  You need to "consult" the completion
+> to know that.  We need to decide when you are allowed
+> to consult the completion.  I have a feeling we are perhaps
+> being a bit too generous already.
+
+You're right of course that an arbitrary coverage needs to refer to the
+completion. But is that really worth it? All of the cases that I've seen
+either were making a class-wide call to Incomplete'Class (using
+access-to-Incomplete'Class) or are assigning concrete instances of
+Incomplete to Complete. The former is useful to make sense out of the extra
+packages necessary for this (to make them useful for more than just breaking
+cycles); I'm not sure that the latter is really valuable in practice.
+
+So I have to wonder the value of messing with these rules. After all, any
+case where these rules would kick in can easily be worked around simply by
+withing the completion's package. I'd guess that 98% of the time, that will
+be necessary anyway, unless my classwide idea becomes popular. And even
+then, we don't need to change type matching. I think we'll need some
+experience using whatever facility we choose before we'll know if we really
+need something fancy.
+
+I would be happy simply making this a part of tagged incomplete types:
+
+   A dereference (...) shall not be of an incomplete type, unless it is a
+tagged incomplete type directly used as an actual parameter to a
+non-dispatching call.
+
+forgetting all of the rest of it until we can see if in fact it comes up in
+practice. (We'll need some implementations to do that.) But I'm willing to
+go further, but not so far as to mess with type matching.
+
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Friday, March 21, 2003  7:02 PM
+
+> 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.
+
+There's no way to tell; I haven't seen any real proposal for limited with
+yet. I've only been discussing the two versions of type stubs - the original
+one I'm working on, and Tucker's child type stubs.
+
+My (very superficial) analysis of 'limited with' suggests that it will have
+much worse visibility issues than either version of type stubs.
+
+Anyway, let's look at this example from the point of view of type stubs
+(note: in type stubs, "limited with" does nothing other than make the
+package available):
+
+    limited with P;
+    with Q;
+    package R is
+        X : P.T; -- Legal? (No, no P.T here.)
+        type T is separate of P.T;
+        Y : T; -- Legal? (No, T is incomplete.)
+    end R;
+
+OK, that's probably not quite the same example. Let's try again:
+
+    limited with P;
+    package S is
+        type T is separate of P.T;
+    end S;
+
+    with Q, S;
+    package U is
+        X : P.T; -- Legal? (No, no P.T here.)
+        Y : S.T; -- Legal?
+    end U;
+
+> 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.
+
+Humm. This does seem to be the case (substituting U for R).
+
+That seals it for me; I'll stick with a separate set of legality rules as
+we'd previously written. We can't make the kind of changes to the visibility
+rules that are contemplated by Tucker; it would take years to debug them
+alone.
+
+Thanks for simplifying my work. :-)
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Monday, March 24, 2003  7:24 AM
+
+> I would be happy simply making this a part of tagged incomplete types:
+>
+>    A dereference (...) shall not be of an incomplete type, unless it is
+> a tagged incomplete type directly used as an actual parameter to a
+> non-dispatching call.
+>
+> forgetting all of the rest of it until we can see if in fact it comes up
+> in practice.
+
+In fact I have been wondering about this lately.  Why do we want these
+new rules about dereferencing anyway?  What purpose do they serve?
+Can't you just "with" the completion and be done with?  It seems to me
+that the incomplete view would mostly be needed in specifications, and
+that dereferencing would mostly be used in bodies, so I'm not sure what
+good it would do to allow you to dereference without seeing the
+completion.
+
+The minutes of the Cupertino meeting have the explanation "Tucker would
+like this to be legal" which seems like a rather weak justification to
+me ;-)
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Monday, March 24, 2003  12:04 PM
+
+Perhaps you are right.  However, this means that
+you have to be very aware whether a given access parameter
+is dispatching or not, because there is an implicit
+dereference of access parameters as a side-effect
+of a dispatching call.  It seems a little unfriendly
+to have to make this big distinction.
+
+**************************************************************
+
+From: Gary Dismukes
+Sent: Monday, March 24, 2003  12:30 PM
+
+I agree that this special rule for dereferencing accesses to tagged
+incomplete values doesn't appear to be very useful.  It seems like
+it just makes the rules more complicated and harder to learn for
+very little gain.  Just because the rule can be relaxed in the tagged
+case doesn't mean it should be.
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Monday, March 24, 2003  12:14 PM
+
+I don't see anything in the language which makes the dispatching case an
+implicit_dereference. That seems like a hole for tagged incomplete types
+(you really do need that to be illegal if you don't have the full type
+around).
+
+Pascal wrote:
+
+> In fact I have been wondering about this lately.  Why do we want these
+> new rules about dereferencing anyway? ...
+
+See the examples I've sent out (twice) for one possible use. Note that I
+admit that I probably could live without that if AI-230 is approved. But I'm
+still not sure that (AI-230) is a good idea.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Monday, March 24, 2003  2:14 PM
+
+I guess I have a hard time believing that the body of CBuild_Menu doesn't
+need to have a "with CBuild_Root_Definition" for other reasons, so it's hard
+to get excited about the possibility to dereference Item.Dialog in the body
+of CBuild_Menu.
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Monday, March 24, 2003   2:59 PM
+
+No, there is nothing that you can use there that you couldn't make visible
+in CBuild_Root. Since CBuild_Root_Definition is defining an abstract type,
+there are no concrete object properties, and the only interesting operations
+are dispatching or class-wide. So the only thing the CBuild_Menu can do with
+an access-to-root-window is make a class-wide or dispatching call on it. By
+including class-wide analogs to any operations in CBuild_Root_Definition,
+all such calls can be made. In this actual case, the only things that the
+menu package ever does with a window is: 1) dispatch on a routine to
+generate code to make a call to create the window (as part of the code that
+responses to the selection of a menu item); 2) dispatch on a routine that
+actually opens a copy of the window (as part of the code that simulates the
+actions of the GUI); 3) call a routine that looks up the window by name
+(when reading the menu object from a file (this is class-wide, and defined
+elsewhere anyway); and 4) dispatch on a routine that returns the name of the
+window (to output into the file when writing a menu object).
+
+The only thing that I can imagine wanting to do that you couldn't do is to
+convert it to some specific type, in order to use operations of that type
+not available on the root type. But that would be very bad object-oriented
+design (you don't cast general things into more more specific types), and it
+normally would be easy to add a dispatching routine to the root to handle
+that generally.
+
+**************************************************************
+
+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: This report can be found in the !appendix of AI-217-7.]
 
 **************************************************************
 

Questions? Ask the ACAA Technical Agent