CVS difference for ais/ai-00277.txt

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

--- ais/ai-00277.txt	2001/10/02 20:50:32	1.4
+++ ais/ai-00277.txt	2002/01/05 01:05:53	1.5
@@ -1,1825 +1,24 @@
-!standard 03.10.01   (02)                              01-09-21  AI95-00277/01
+!standard 03.10.01   (02)                              02-01-04  AI95-00277/02
 !class amendment 01-09-21
 !status work item 01-09-21
 !status received 01-09-21
 !priority Medium
 !difficulty Hard
-!subject Handling mutually recursive types via separate incomplete types
+!subject (Deleted)
 
 !summary
 
-A new construct, called a separate incomplete type, is proposed
-as a potential solution to the "mutually recursive types across packages"
-problem. This is an alternative to the "with type" proposal of AI-217 and
-the "package abstract" proposal of AI-271.
+This AI is now the third alternative of AI95-00217 (AI95-00217-03).
 
-A separate incomplete type is an incomplete type which is never completed.
-Another type can be "bound" to the separate incomplete type, which then allows
-the types to be used interchangeably.
-
 !problem
 
-Ada only allows mutually recursive types to be declared if they
-are all declared within the same library unit. This can force
-all of the major data structures of a program into a single library unit,
-which is clearly undesirable in some situations.
-
-The goal of the proposed features is to allow mutual recursion among separately
-compiled types (types containing (pointers to) each other as components, and
-primitive operations with (pointers to) each other as parameters.) And to do
-this in a way that doesn't place any other restrictions on the programmer.
-
 !proposal
 
-   incomplete_modifier ::= IS TAGGED | IS SEPARATE | IS TAGGED SEPARATE;
-   incomplete_type_declaration ::=
-       TYPE defining_identifier [discriminant_part] [incomplete_modifier];
-
-
-An incomplete type containing the reserved word "tagged" (an "incomplete tagged
-type") may be used as the type of a formal parameter prior to its completion,
-in addition to the normal places where an incomplete type may be used. Also,
-the Class attribute is defined for an incomplete tagged type. The class-wide
-type denoted by the Class attribute of an incomplete type may also be used as
-the type of a formal parameter. The Class attribute of a non-tagged incomplete
-type is considered obsolescent. An incomplete tagged type must be completed by
-a tagged type.
-
-Note that we are not proposing that an incomplete tagged type may be
-used as a return type, because of the many special rules and implementation
-issues associated with returning tagged types (e.g. functions becoming
-abstract, accessibility checks on returning limited by-reference types,
-dispatching on result coupled with tag indeterminacy, finalization associated
-with returning potentially controlled types, etc.)
-
-An incomplete type containing the reserved word "separate" (a "separate
-incomplete type") is completed by a type declaration with a completion_clause.
-
-    completion_clause ::= for <separate_incomplete_type_name>
-
-    full_type_declaration ::=
-       type <Defining_Identifier> [completion_clause] [known_discriminant_part]
-           is type_definition;
-       ...
-
-The name in a completion_clause must name a visible separate incomplete type.
-There is a post compilation rule that a separate incomplete type may have
-only a single completion. The type defined by a type declaration with a
-completion_clause is known as a completing type for the separate incomplete
-type. The rules in 3.10.1(4) about a completion for an incomplete type
-apply to a completing type.
-
-Where the completing type (or the full type declaration for the completing
-type, if the completing type is a private type) is visible, the separate
-incomplete type name (and the names of any subtypes of it) is treated as a
-subtype naming the completing type. (That is, it is a alternative name for
-the completing type.) In other places, the standard rules for the use of the
-name of an incomplete type apply. A separate incomplete type is exempted from
-the rule that completed declarations are hidden from all visibility (8.3(19)).
-(Since the name is declared in an different scope, there is no need to hide it;
-doing so probably would be additional, unnecessary work.)
-
-A separate incomplete type can be frozen; it does not need a completion when
-it is frozen. Only non-separate incomplete types are excluded from freezing
-at the end of a scope (13.14(3)).
-
-
 !discussion
 
-The concept of a forward or separate incomplete type has been proposed
-in the past. At the time, other proposals looked more attraction. However,
-the complexity of those proposals (particularly the far reaching effects
-of adding a new kind of compilation unit) makes them less attractive to
-solve these problems.
-
-There seem to be two general ways this kind of problem is solved in
-other languages. One approach is to permit unrestricted forward
-references. This is the approach adopted by Eiffel, Java, and Smalltalk.
-The other approach is to require "forward" or "incomplete" declarations,
-sometimes called "signatures" or "partial revelations." This is generally
-the approach adopted by Ada, as well as Pascal, Modula, ML, C/C++, etc.
-
-We chose the simple approach of extending a single existing Ada feature, rather
-than adding a basket of heavy new features to provide the needed capability.
-This simplifies both the conceptual burden and the implementation cost.
-
-The model of a separate incomplete type does not add any new implementation
-burden. That's because it is very similar to the incomplete-deferred-to-body
-which Ada 95 already has. The compiler does not need to know the real type
-involved as long as the incomplete usage rules are enforced.
-
-Determining the representation of an access type that designates a
-separate incomplete type could be a problem for some implementations that
-select the representation of an access type based on the designated type.
-However, this would be no different than doing that for a type whose completion
-is deferred to the body. So such implementations must already be able to
-handle this somehow.
-
-Since an access type that designates a separate incomplete type is a normal
-declaration, representation clauses (for storage pools, for instance) can be
-used as needed. This eliminates many of the problems found in the "with type"
-proposal. Note that such an access type can be used normally (including
-allocators, deallocators, and the like) when the completing type is visible.
-
-
-This proposal allows the separate incomplete type to not be completed at all
-in the program. There is no problem with not having a completion (no object of
-the type could be created), and there is no implementation problem. Not having
-a completion can be useful in the prototype stages of a program, and also
-can be useful for a program with multiple implementations. (For instance,
-a compiler front-end could have an incomplete type for code generation
-information. A checkout version of the compiler, with no need for code
-generation, would not need to complete the incomplete type.)
-
-
-An alternative model where the place and name of the completion is specified
-in the separate incomplete type's declaration was considered. This model was
-rejected for two reasons:
-   -- The name of the completion does not exist at the point of the separate
-      incomplete declaration. Indeed, we must not have a semantic dependence
-      on the unit of the completion, or we will not be able to solve the
-      mutual dependence problem. Thus, describing the semantics of such a
-      requires a new language mechanism.
-   -- We want to insure that the separate incomplete type is visible to the
-      completion. This would require additional rules.
-The model chosen has neither of these problems. Since we don't try to reference
-the completion in the separate declaration, we don't have to describe what it
-means. A comment may be appropriate, but that is out of control of the
-standard. Secondly, by requiring the name of the separate incomplete type in
-the completing declaration, we automatically require that the incomplete type
-is visible.
-
-
-The legality checks for the use of the name of the separate incomplete type
-depend on the visibility of the completing type. This works because types
-can only be hidden from all visibility by a completion. We don't want to
-use "scope" here, as the scope of a library-level type includes the entire
-program. We only want to allow full use of the type where the package
-containing the completion is withed. (Keep in mind we are talking about
-"visibility", not "direct visibility", here.)
-
-
-An alternative model where the separate incomplete type is never completed
-(a "forever incomplete type") was considered. In this model, a type is "bound"
-to a separate incomplete type. Then, anywhere in the scope of the binding, the
-two types are considered equivalent. In this model, the separate incomplete
-type can never be used anywhere declare an object, write an allocator, or
-instantiate a generic. This seems unnecessary, and the difficulty of writing
-the needed type matching rules caused it to run aground.
-
-
-The model chosen allows separate incomplete types to be frozen, eliminating the
-anomaly of having unfrozen types imported from other units. It also eliminates
-having types that are never frozen anywhere in the program.
-
-The author would prefer to change the freezing model for incomplete types to
-the following:
-    - Incomplete types freeze like other types. (The "except incomplete types"
-      in 13.14(3) is deleted.)
-    - When an incomplete type is frozen, if the incomplete type is not separate,
-      and not declared in the private part of a package specification, then
-      it must have already been completed.
-The author believes this is equivalent (with one minor exception) to the
-existing model, as the name usage rules 3.10.1(5-9) prevent any freezing
-before the completion anyway. (The exception is that the completion of an
-incomplete-deferred-to-body could appear after a body in the package body.)
-This change would eliminate the anomaly of unfrozen types ever existing outside
-of their declarative_part. This was not done mainly to avoid cluttering this
-proposal with a non-required change (thus making it seem bigger than it is).
-
-
-The syntax for completion_clause does not apply to task or protected types
-in this proposal. These were omitted solely to keep the proposal simple; there
-is no known need to omit them. Adding them would require four additional
-syntax changes.
-
 !example
 
-Here is the classic case of mutual dependence, where an employee
-belongs to a particular department, and a department has a manager who
-is an employee. (We assume the use of tagged types here to illustrate the
-use of tagged incomplete types.)
-
-    package Employees_Interface is
-        type Employee is tagged separate;
-        type Emp_Ptr is access all Employee'Class;
-    end Employees_Interface;
-
-    package Departments_Interface is
-        type Department is tagged separate;
-        type Dept_Ptr is access all Department'Class;
-    end Departments_Interface;
-
-    with Departments_Interface, Employees_Interface;
-    package Employees is
-        type Employee for Employees_Interface.Employee is tagged private;
-        procedure Assign_Employee(E : in out Employee;
-                                  D : in out Departments_Interface.Department);
-        ...
-        function Current_Department(D : in Employee) return
-            Departments_Interface.Dept_Ptr;
-    end Employees;
-
-    with Departments_Interface, Employees_Interface;
-    package Departments is
-        type Department for Departments_Interface.Departments is tagged private;
-        procedure Choose_Manager(D : in out Department;
-                                 Manager : in out Employees_Interface.Employee);
-        ...
-    end Departments;
-
 !ACATS test
 
 !appendix
-
-From: Dan Eilers
-Sent: Wednesday, June 20, 2001, 5:04 PM
-
-I agree with Tucker et al that the "with type" proposal (AI 217) is
-misguided, because it involves implicit type declarations and their
-enclosing "ghost" library units.  These implicit declarations
-provide no place to attach pragmas, representation clauses or
-access type declarations.  They also don't work well in library-based
-implementations, because such implementations can't easily go looking
-for the source to an uncompiled unit to see what types are declared
-inside it.  Instead, library-based implementations would probably need
-some new compilation mode that enters the ghost library packages into
-the library.
-
-While the "package abstracts" proposal (AI 271) solves these problems,
-I agree with Ed Schonberg et al that this solution is too heavy.  It
-increases the number of package parts to 4 (abstract, visible spec,
-private, body); it adds a new kind of library unit, causing impact to
-tools that manipulate libraries, e.g. compilation-order tools; and
-it adds a new kind of "with" clause, e.g. abstract with p, or
-with p abstract, or with p'abstract.
-
-I agree with Bob Duff et al that the alternative of bolting the package
-abstract to the front of the package spec isn't attractive.  It doesn't
-reduce the 4 kinds of package parts; it doesn't eliminate the need
-for some new compilation mode that enters just the package abstract into
-the library (although such a new compilation mode might be easier to
-define and implement); and it doesn't eliminate the need for the
-new kind of "with" clause.
-
-The essence of the "package abstracts" proposal is that it provides
-a place where an incomplete type can be declared whose full declaration
-is expected to be found elsewhere.  (The name of the package abstract
-provides the indication as to where the full type declaration is expected
-to be found.)  But there seems to be no need for a new type of library
-unit to do this job.  Instead, a pragma (or spiffy new syntax for
-incomplete type declarations if you prefer) would suffice.
-
-Instead of:
-
-   package abstract Employees is
-        type Employee;
-        type Emp_Ptr is access all Employee;
-    end Employees;
-
-You would have:
-
-   package unrelated is
-       type Employee;
-       pragma completed_elsewhere(Employee, where => Employees);
-       type Emp_Ptr is access all Employee;
-   end unrelated;
-
-This involves no new package parts, no new library units, and no
-new kinds of "with" clauses.  If packages Employees and Departments
-were both children of the same parent, then the incomplete
-declarations could simply go in the parent.
-
-        -       -       -       -       -       -       -
-
-As a further refinement, I would note that the "where" parameter
-to pragma completed_elsewhere is anomalous, since it names a
-package that isn't visible, and normally isn't even available in
-the library.  I don't think the "where" parameter is actually
-necessary.  Instead of the incomplete type declaration indicating
-where the full type will be (so that the compiler can ultimately
-connect the two), the full declaration could indicate what
-incomplete type it is completing.  This could be done with a
-pragma (or spiffy new syntax if you prefer).
-
-So instead of:
-
-    package abstract Employees is
-        type Employee;
-        type Emp_Ptr is access all Employee;
-    end Employees;
-
-    package abstract Departments is
-        type Department;
-        type Dept_Ptr is access all Department;
-    end Departments;
-
-    with Departments'abstract;
-    package Employees is
-        type Employee is private;
-        type Emp_Ptr is access all Employee;
-        procedure Assign_Employee(E : access Employee;
-          D : access Departments.Department);
-        ...
-        function Current_Department(D : access constant Employee) return
-          Departments.Dept_Ptr;
-    end Employees;
-
-    with Employees'abstract;
-    package Departments is
-        type Department is private;
-        type Dept_Ptr is access all Department;
-        procedure Choose_Manager(D : access Department;
-          Manager : access Employees.Employee);
-        ...
-    end Departments;
-
-we would have:
-
-   package unrelated is
-       type Employee;  pragma completed_elsewhere(Employee);
-       type Emp_Ptr is access all Employee;
-
-       type Department;  pragma completed_elsewhere(Employee);
-       type Dept_Ptr is access all Department;
-   end unrelated;
-
-
-    with Unrelated;
-    package Employees is
-        type Employee is private;
-           pragma completion(Employee, from => Unrelated);
-        type Emp_Ptr is access all Employee;
-        procedure Assign_Employee(E : access Employee;
-          D : access Unrelated.Department);
-        ...
-        function Current_Department(D : access constant Employee) return
-          Unrelated.Dept_Ptr;
-    end Employees;
-
-    with Unrelated;
-    package Departments is
-        type Department is private;
-           pragma completion(Department, from => Unrelated);
-        type Dept_Ptr is access all Department;
-        procedure Choose_Manager(D : access Department;
-          Manager : access Unrelated.Employee);
-        ...
-    end Departments;
-
-
-This opens up the possibility of more than one completion of the same
-incomplete type, which may be unnecessary, but doesn't seem harmful.
-
-To summarize:
-   no new kinds of library units
-   no new kinds of package parts
-   no new kinds of with clauses
-   no impact to compilation-order tools
-   no new compilation modes
-   no forward references to uncompiled library units
-   no problems with library-based implementations
-   no new syntax unless we want it (we probably do).
-
-*************************************************************
-
-From: Randy Brukardt
-Sent: Tuesday, July 3, 2001, 6:14 PM
-
-Re: Dan Eiler's proposal.
-
-I'm quite surprised that no one seriously has looked at this proposal. It seems
-to me that it eliminates some of the problems of the abstract package and
-simplifies it a lot without necessarily losing the important features.
-
-The basic proposal is to introduce a new kind of incomplete type that NEVER
-needs to be completed. It would have syntax like (Dan used pragmas, but they're
-really ugly for something that will be commonly used):
-
-    type <Defining_Identifier> is separate;
-    type <Defining_Identifier> is tagged separate;
-
-The rules for packages would be unchanged. The tagged kind of separate
-incomplete type would allow 'Class and use as the type name in parameter
-declarations (but not function returns).
-
-My immediate reaction was that this would be hard to implement. But, on further
-reflection, I realized that as long as the incomplete rules were enforced
-everywhere that the incomplete type is visible, the compiler NEVER needs to
-know the real type involved. Moreover, this type could not be used in an
-allocator or a generic, so we would get the restrictions we need for free.
-(And it is rather like an incomplete type deferred to a body, for which the
-compiler can't assume anything anyway.)
-
-The completion would include a new clause in the type declaration:
-
-    type <Defining_Identifier> [completion_clause] ...
-
-    completion_clause ::= for <type_name>
-
-[I'd rather use "completes" here, but that would introduce a new reserved word.
-I also looked at "declare" for this use, but it reads funny. I'm sure someone
-will have nifty syntax for this.]
-
-There would be a post-compilation check that all "is separate" types are
-completed exactly once. (I don't think that there is any benefit to allowing
-multiple completions, because the types have to be considered the same in some
-scopes, and that could lead to a situation where A = P and B = P, but A /= B.)
-
-To recast Dan's example (fixing a couple of errors):
-
-    package Partial_Definitions is
-       type Employee is separate;
-       type Emp_Ptr is access all Employee;
-
-       type Department is separate;
-       type Dept_Ptr is access all Department;
-   end Partial_Definitions;
-
-   with Partial_Definitions;
-   package Employees is
-       type Employee for Partial_Definitions.Employee is private;
-       type Emp_Ptr is access all Employee;
-       procedure Assign_Employee(E : access Employee;
-          D : access Partial_Definitions.Department);
-        ...
-       function Current_Department(D : access constant
-          Employee) return Partial_Definitions.Dept_Ptr;
-   end Employees;
-
-   with Partial_Definitions;
-   package Departments is
-       type Department for Partial_Definitions.Department is private;
-       type Dept_Ptr is access all Department;
-       procedure Choose_Manager(D : access Department;
-          Manager : access Partial_Definitions.Employee);
-        ...
-   end Departments;
-
-
-Now to look at the possible problems:
-
-Determining the representation of Partial_Definitions.Emp_Ptr would be a
-problem for some implementations that select the representation of an access
-type based on the designated type. However, this would be no different than
-doing that for a type whose completion is deferred to the body. So such
-implementations must already be able to handle this.
-
-Similarly, Partial_Definitions.Emp_Ptr would never be frozen, but again we
-already have to handle that.
-
-Partial_Definitions.Emp_Ptr would never have allocators defined for it.
-Probably it would be best that it has no pool at all. That means that any
-allocations would have to be converted to the type. Similarly,
-Unchecked_Deallocation couldn't be instantiated for it. OTOH, other uses would
-not need conversions. So that doesn't seem too bad. If it is a real problem,
-AI-230 may help solve that. Or we could simply define such types to be
-equivalent (that couldn't be a compatibility problem, as Ada 95 has no such
-types!). But then we'd have to deal with defining the pool for the incomplete
-access type.
-
-The interesting question is exactly what does the "completion_clause" mean.
-The idea appears to be that inside of package Employees,
-Partial_Definitions.Employee and Employees.Employee are considered to be the
-same type for all purposes including resolution. (That's how we get conversions
-between Partial_Definitions.Emp_Ptr and Employees.Emp_Ptr.) Whether that should
-hold outside of Employees at places that have visibility on both Employees and
-on Partial_Definitions is an open question. Off-hand, I don't see how this
-could cause a problem, but perhaps someone else can.
-
-
-So, at first look, this seems like a useful idea to pursue. It doesn't have any
-elaboration or "new unit kind" problems as package abstract does, and it
-probably doesn't have the visibility issues either (depending on the exact
-definition of when the types are considered the same). It's similar to the
-current "with type" in that the access type equivalence isn't perfect, but it
-looks much easier to fix than rather than with "with type".
-
-So, what is wrong with this idea? Should it be written up completely?
-
-*************************************************************
-
-From: Robert Dewar
-Sent: Tuesday, July 3, 2001, 7:55 PM
-
-I certainly prefer the separate idea to the package abstract proposal from
-a language design point of view, but it is not clear to me that it satisfies
-all the Java interface requirements. I definitely think it is worth writing
-up the idea completely.
-
-*************************************************************
-
-From: Randy Brukardt
-Sent: Tuesday, July 3, 2001, 8:19 PM
-
-Humm. The only Java interface requirement that I know of that we're trying to
-address with this proposal is the mutually dependent types problem. And Java
-types are essentially tagged types in Ada, so with the tagged incomplete type,
-we get the needed functionality. I think. Is there something else that I've
-missed?
-
-*************************************************************
-
-From: Ted Baker
-Sent: Thursday, July 5, 2001, 7:05 AM
-
-I've been lurking out here watching the discussion on the package abstract
-idea, dismayed by the conceptual complexity and ugliness.  The Dan/Randy
-separate proposal seems much cleaner.  I hope you can work it out to everyone's
-satisfaction.
-
-*************************************************************
-
-From: Tucker Taft
-Sent: Monday, July 9, 2001, 3:51 PM
-
-Ted Baker wrote:
->
-> I've been lurking out here watching the discussion on the package abstract
-> idea, dismayed by the conceptual complexity and ugliness.  The Dan/Randy
-> separate proposal seems much cleaner.  I hope you can work it out to everyone's
-> satisfaction.  --Ted
-
-I agree that Dan's proposal, with some of Randy's suggestions,
-is a direction worth pursuing.  This is not too far from
-a direction suggested in the past using pragma Import
-and pragma Export applied to types, analogous to the
-trick that can be used to implement a subprogram declared
-in one package with a subprogram declared in another package.
-
-I would like to know at least the name of the
-package where the full type definition is provided,
-and I wouldn't mind requiring it to be a child
-of the package where the incomplete type is declared,
-ensuring that the incomplete/separate type's declaration
-is directly visible at the point of the full type definition.
-I would require that the name of the full type in the child
-match the name of the incomplete type in its parent.
-
-Hence, something like:
-
-   package P is
-       type T is separate(C);  -- is completed
-                               -- in child "C" of P.
-       ...
-   end P;
-
-   package P.C is
-       type T is ...
-   end P.C;
-
-*************************************************************
-
-From: Randy Brukardt
-Sent: Friday, July 13, 2001, 6:15 PM
-
-> I agree that Dan's proposal, with some of Randy's suggestions,
-> is a direction worth pursuing.  This is not too far from
-> a direction suggested in the past using pragma Import
-> and pragma Export applied to types, analogous to the
-> trick that can be used to implement a subprogram declared
-> in one package with a subprogram declared in another package.
-
-Except this is a model that makes sense, while using pragma Import and Export
-says KLUDGE in large, flashing letters.
-
-> I would like to know at least the name of the
-> package where the full type definition is provided,
-> and I wouldn't mind requiring it to be a child
-> of the package where the incomplete type is declared,
-> ensuring that the incomplete/separate type's declaration
-> is directly visible at the point of the full type definition.
-> I would require that the name of the full type in the child
-> match the name of the incomplete type in its parent.
->
-> Hence, something like:
->
->    package P is
->        type T is separate(C);  -- is completed
->                                -- in child "C" of P.
->        ...
->    end P;
->
->    package P.C is
->        type T is ...
->    end P.C;
-
-Well, this is almost OK, but I think it has some problems.
-
-First, describing the semantics of the name in the separate is going to be
-interesting. It has to reference something not declared yet, and about all we
-can say about it is that it is a library unit -- which doesn't even need to
-exist yet. Indeed, there must be no requirement that it exist.
-
-Second, restricting the completion to a child is a non-starter. I certainly
-don't think people would be happy to have to rename all of their packages in
-order to use this feature. It is particularly bad, because the parent
-(presumably with the original name) would contain just the partial definitions,
-while the child would contain the "meat" -- the stuff that exists now. So every
-reference the package would have to be changed.
-
-Moreover, I don't think such a restriction would work well with Robert Dewar's
-"only reason for this feature" -- interfacing to Java. If you have two Java
-classes Class_A and Class_B that are mutually recursive, this idea would force
-you to introduce not only another package, but one whose name will show up
-everywhere:
-
-    package Java_Stuff is
-       type Class_A is tagged separate (A);
-       type Class_A_Access is access all Class_A;
-       type Class_B is tagged separate (B);
-       type Class_B_Access is access all Class_B;
-    end Java_Stuff;
-
-    package Java_Stuff.A is
-       type Class_A is tagged ...
-       ...
-    end Java_Stuff.A;
-
-    package Java_Stuff.B is
-       type Class_B is tagged ...
-       ...
-    end Java_Stuff.B;
-
-I think it would be much cleaner to say:
-
-    package Abstract_A_and_B is
-       type Class_A is tagged separate (A);
-       type Class_A_Access is access all Class_A;
-       type Class_B is tagged separate (B);
-       type Class_B_Access is access all Class_B;
-    end Abstract_A_and_B;
-
-    with Abstract_A_and_B;
-    package A is
-       type Class_A is tagged ...
-       ...
-    end A;
-
-    with Abstract_A_and_B;
-    package B is
-       type Class_B is tagged ...
-       ...
-    end B;
-
-...because then the "abstract" package never appears in uses of Class_A or
-Class_B. Only the declarations of Class_A and Class_B need worry about it.
-
-It is especially annoying that there is no technical reason (at least that I
-know) for this restriction: it would just be a language designer's feel for
-"the best way to do it". There doesn't seem to be any technical need for direct
-(or any!) visibility on the incomplete type in order to complete it - the type
-has no operations (primitive or otherwise) anyway. And the visibility of uses
-doesn't seem to matter either: you just get whatever view you have.
-
-So I would make the name a library unit name, and drop any child requirement.
-
-A third point (just a quibble) is that it really is necessary for readability
-to mention that this type is a completion (even if the name of the type is
-required to be the same). So, I'd expect to always put in a comment:
-    -- Completes Abstract_A_and_B.Class_B.
-It seems like it would be helpful to include this in the syntax somehow, just
-as is done with subprogram names on "end". (Aside: I sure wish "end record;"
-was "end <type_name>;", 'cause that's what I write every time anyway. :-)
-
-Anyway, it seems that I've volunteered again :-) to write this up. I'm not sure
-whether to replace AI-271 with this proposal, or to open a third AI for this
-third approach. Suggestions?
-
-*************************************************************
-
-From: Tucker Taft
-Sent: Monday, July 16, 2001, 5:31 PM
-
-Randy Brukardt wrote:
-> >
-> >    package P is
-> >        type T is separate(C);  -- is completed
-> >                                -- in child "C" of P.
-> >        ...
-> >    end P;
-> >
-> >    package P.C is
-> >        type T is ...
-> >    end P.C;
->
-> Well, this is almost OK, but I think it has some problems.
->
-> First, describing the semantics of the name in the separate is going to be
-> interesting. It has to reference something not declared yet, and about all
-> we can say about it is that it is a library unit -- which doesn't even need
-> to exist yet. Indeed, there must be no requirement that it exist.
-
-This is analagous to a subunit.  The subunit need not
-exist at the point when the stub appears, but it logically
-appears there.  So this seems pretty similar.
-
->
-> Second, restricting the completion to a child is a non-starter. I certainly
-> don't think people would be happy to have to rename all of their packages in
-> order to use this feature. It is particularly bad, because the parent
-> (presumably with the original name) would contain just the partial
-> definitions, while the child would contain the "meat" -- the stuff that
-> exists now. So every reference the package would have to be changed.
-
-Hmmm... I suppose, though this seems like something
-that would have to be mostly for new code.  Also,
-library-unit renaming would allow the child to be
-renamed as a top-level unit.
-
->
-> Moreover, I don't think such a restriction would work well with Robert
-> Dewar's "only reason for this feature" -- interfacing to Java. If you have
-> two Java classes Class_A and Class_B that are mutually recursive, this idea
-> would force you to introduce not only another package, but one whose name
-> will show up everywhere:
->
->     package Java_Stuff is
->        type Class_A is tagged separate (A);
->        type Class_A_Access is access all Class_A;
->        type Class_B is tagged separate (B);
->        type Class_B_Access is access all Class_B;
->     end Java_Stuff;
->
->     package Java_Stuff.A is
->        type Class_A is tagged ...
->        ...
->     end Java_Stuff.A;
->
->     package Java_Stuff.B is
->        type Class_B is tagged ...
->        ...
->     end Java_Stuff.B;
-
-Actually, Java classes are essentially always declared
-in (Java) packages, so the Ada package corresponding
-to the Java package is a natural place for these.
-Also, the pointer type is the one that Java users will
-use.  The package where the operations are declared
-will not be as important if the obj.operation notation
-is used.
-
->
-> I think it would be much cleaner to say:
->
->     package Abstract_A_and_B is
->        type Class_A is tagged separate (A);
->        type Class_A_Access is access all Class_A;
->        type Class_B is tagged separate (B);
->        type Class_B_Access is access all Class_B;
->     end Abstract_A_and_B;
->
->     with Abstract_A_and_B;
->     package A is
->        type Class_A is tagged ...
->        ...
->     end A;
->
->     with Abstract_A_and_B;
->     package B is
->        type Class_B is tagged ...
->        ...
->     end B;
->
-> ...because then the "abstract" package never appears in uses of Class_A or
-> Class_B. Only the declarations of Class_A and Class_B need worry about it.
-
-I guess I am still not convinced.  I think we need some
-real examples, not just package A and B, to see which
-works better.
-
-> It is especially annoying that there is no technical reason (at least that I
-> know) for this restriction: it would just be a language designer's feel for
-> "the best way to do it". There doesn't seem to be any technical need for
-> direct (or any!) visibility on the incomplete type in order to complete it -
-> the type has no operations (primitive or otherwise) anyway. And the
-> visibility of uses doesn't seem to matter either: you just get whatever view
-> you have.
->
-> So I would make the name a library unit name, and drop any child
-> requirement.
-
-But it seems important to know that a given type is
-completing an incomplete type, because representation
-may depend on this.  I would think we would certainly
-require that that package with the full type "with" the
-package with the incomplete type, so given that, it seemed
-better to just make it into a child, which always implicitly
-"with"s its parent.
-
->
-> A third point (just a quibble) is that it really is necessary for
-> readability to mention that this type is a completion (even if the name of
-> the type is required to be the same). So, I'd expect to always put in a
-> comment:
->     -- Completes Abstract_A_and_B.Class_B.
-> It seems like it would be helpful to include this in the syntax somehow,
-> just as is done with subprogram names on "end". (Aside: I sure wish "end
-> record;" was "end <type_name>;", 'cause that's what I write every time
-> anyway. :-)
->
-> Anyway, it seems that I've volunteered again :-) to write this up. I'm not
-> sure whether to replace AI-271 with this proposal, or to open a third AI for
-> this third approach. Suggestions?
-
-I hate to see a proliferation of AIs which are alternatives
-of the same thing.  I guess I would rather see these all
-part of the same AI, put forth as alternatives.  Once
-we ultimately pick one for further refinement, we will want
-the others in the appendix or rationale as rejected alternatives.
-Hence, it seems to me they all belong in the same AI.
-Perhaps we need to recognize the importance of "alternatives"
-in amendment AIs.
-
-*************************************************************
-
-From: Randy Brukardt
-Sent: Tuesday, July 17, 2001, 4:41 PM
-
-Tucker, responding to me responding to him, wrote:
-> > >
-> > >    package P is
-> > >        type T is separate(C);  -- is completed
-> > >                                -- in child "C" of P.
-> > >        ...
-> > >    end P;
-> > >
-> > >    package P.C is
-> > >        type T is ...
-> > >    end P.C;
-> >
-> > Well, this is almost OK, but I think it has some problems.
-> >
-> > First, describing the semantics of the name in the separate is going to be
-> > interesting. It has to reference something not declared yet, and about all
-> > we can say about it is that it is a library unit -- which doesn't even need
-> > to exist yet. Indeed, there must be no requirement that it exist.
->
-> This is analagous to a subunit.  The subunit need not
-> exist at the point when the stub appears, but it logically
-> appears there.  So this seems pretty similar.
-
-I think you missed the point. In a subunit, there is no attempt to name some
-unit that will exist sometime in the future. The stub is a declaration of a
-some entity, and that entity actually exists there.
-
-OTOH, the unit named in your proposed syntax is not declared anywhere. And the
-appearance in the separate type declaration certainly is not a declaration, nor
-does some random package spec logically exist at this point.
-
-Traditionally, Ada 95 requires the completor to name the completee (think
-"separate" clause in subunits). The partial declaration does not indicate much
-(if anything) about the completor.
-
-Thus, I think it makes the most sense for the completion to indicate that it is
-completing a separate, rather than the separate trying to name the location of
-the completion. (But I don't feel that strongly about this.)
-
-> > Second, restricting the completion to a child is a non-starter. I certainly
-> > don't think people would be happy to have to rename all of their packages in
-> > order to use this feature. It is particularly bad, because the parent
-> > (presumably with the original name) would contain just the partial
-> > definitions, while the child would contain the "meat" -- the stuff that
-> > exists now. So every reference the package would have to be changed.
->
-> Hmmm... I suppose, though this seems like something
-> that would have to be mostly for new code.  Also,
-> library-unit renaming would allow the child to be
-> renamed as a top-level unit.
-
-Well, I suppose. *I* have existing code that desperately needs this feature,
-and I would certainly want to use it when it is available.
-
-But this means that virtually my entire program would have to be children of
-some parent. The effect would be that every object would have a parent package
-containing the abstract interface; and a child containing the real definition,
-and a library unit renames to a reasonable name.
-
->...
->
-> Actually, Java classes are essentially always declared
-> in (Java) packages, so the Ada package corresponding
-> to the Java package is a natural place for these.
-> Also, the pointer type is the one that Java users will
-> use.  The package where the operations are declared
-> will not be as important if the obj.operation notation
-> is used.
-
-I know all of this (with the possible exception of the last), and I don't see
-what it has to do with my point. Every Java object is converted into an Ada
-package. But if incomplete types are restricted to children, each such package
-will necessarily be two such packages. And the real implementation will be in
-a child. So, the package names will not be a direct mapping from Java, and
-you'll need a library renames to get close.
-
-> > It is especially annoying that there is no technical reason (at least that
-> > I know) for this restriction: it would just be a language designer's feel
-> > for "the best way to do it". There doesn't seem to be any technical need
-> > for direct (or any!) visibility on the incomplete type in order to
-> > complete it - the type has no operations (primitive or otherwise) anyway.
-> > And the visibility of uses doesn't seem to matter either: you just get
-> > whatever view you have.
-> >
-> > So I would make the name a library unit name, and drop any child
-> > requirement.
->
-> But it seems important to know that a given type is
-> completing an incomplete type, because representation
-> may depend on this.  I would think we would certainly
-> require that that package with the full type "with" the
-> package with the incomplete type, so given that, it seemed
-> better to just make it into a child, which always implicitly
-> "with"s its parent.
-
-If your initial statement is true (and it seems to be), then it is imperative
-that the completing declaration include syntax to specify that it is a
-completion. (So all of the reader, the writer, and the compiler knows certainly
-that it is a completion, and of what.) That syntax would necessarily include
-the name of the type being completed, so it follows that the package would
-have to be withed (from the normal visibility rules). Once we have this, there
-doesn't seem to be any need to restrict where this is used.
-
-*************************************************************
-
-From: Pascal Leroy
-Sent: Tuesday, July 17, 2001, 7:11 AM
-
-Robert says:
-
-> The main argument in favor of this feature at all (at least the market
-> argument as opposed to "this would be nice to have") is to mimic C++ and
-> Java existing code. So to me the only strong argument for nested package
-> abstracts would be an argument that they are useful from this point of view.
-> I do not see that this is the case, but am not really familiar enough to say.
-
-I have an entirely different perspective here.  I don't think Rational will
-implement interfacing with C++ or Java in the foreseeable future (I don't think
-we have seen much demand).  On the other hand, mutually dependent types show up
-all the time in OO designs (in particular when mapping a UML model to Ada).  So
-I believe we need a general solution to this issue, regardless of interfacing
-consideration (general doesn't mean overengineered, of course).
-
-I guess different vendors see different user communities...
-
-*************************************************************
-
-From: Erhard Ploederedere
-Sent: Wednesday, July 18, 2001, 6:56 AM
-
-What I would like to see at some point is one write-up that summarizes the
-pros and cons of the three or more approaches in a single document. With
-three or more separate write-ups, these comparisons are harder to make.
-
-I guess I am asking for a summarizing Study Note rather than multiple AIs,
-which describe a single approach each and collect random comments in the
-appendix. This study note may well be the eventual "master AI-171".
-
-*************************************************************
-
-From: Randy Brukardt
-Sent: Wednesday, July 18, 2001, 2:26 PM
-
-Sounds wonderful. Are you volunteering to write it? (So far, with this
-proposal, the person who has floated an idea has been tagged to write it up.)
-
-I know that the limited time I have available will prevent me from doing
-anything like that until at least November. In the mean time, we're going to
-have a meeting, and I need to rewrite several AIs (including the "type
-separate" proposal). We're going to need something to discuss in the mean time.
-
-If you want the simple version, here it is:
-
-    "with type"
-        Con: Can't handle access types (due to representation issues).
-             Implementation needs "pseudo packages" internally.
-             What happens when multiple paths to the same item "meet"?
-        Pro: Easy to describe to users.
-    "package abstract"
-        Con: Heavy, complex mechanism. Complex visibility issues to work out.
-             New kind of compilation unit affects all tools (alternatives
-             avoiding compilation unit has similar effect on tools because the
-             source must be compiled in two different ways).
-        Pro: Handles access types cleanly.
-    "type separate"
-        Con: Must introduce extra packages (either "unnecessary" parents with
-             Tucker's rules or "unrelated" ones with Dan's/Randy's rules).
-             No allocators/deallocators on access types with designated types
-             of this kind.
-             (Probably others, once a proposal is made and picked apart.)
-        Pro: No new kind of units. No new visibility issues. Access types can
-             be handled (representation clauses can be given if needed). Model
-             is easy to understand (it is an extension of existing rules). No
-             run-time implementation problems; the implementation is identical
-             to incomplete-completed-in-body.
-
-*************************************************************
-
-From: Dan Eilers
-Sent: September 6, 2001  6:17 PM
-
-The writeup for this AI should probably reference:
-
-http://home.bluemarble.net/~jvolan/WithingProblem/FAQ.html#forward_incompletes
-
-*************************************************************
-
-From: Tucker Taft
-Sent: Saturday, September 22, 2001, 7:56 AM
-
-I like almost everything about this proposal except the syntax
-(and perhaps the use of the phrase "separate incomplete type"
-rather than something like "type stub" for the incomplete type).
-
-How about defining a new kind of "representation" clause:
-
-    for <full_type> use type <separate_incomplete_type>;
-
-This reads better to me.  It also allows us to associate
-task types and protected types with the separate incomplete type.
-And it doesn't further muck up the syntax for declaring a type,
-which is already one of the most nightmarish parts of the
-Ada grammar.  Clearly this sort of "representation" clause
-should have to be in the visible part of the package if the
-connection between the two types is to be visible outside the package.
-
-Another alternative, which would eliminate the need completely
-for new syntax, would be something like:
-
-     for <full_type>'Base use <separate_incomplete_type>;
-
-Attribute 'Base is not quite right, of course, but something
-else might be (e.g. for <full_type>'Interface use ... or
-for <full_type>'Stub use ...).
-
-One particularly nice feature of this proposal which I didn't
-realize before is the multiple-implementation concept.  You
-could have multiple completions of the same type stub, and use
-a "with" clause on the main subprogram to determine which one
-gets included in a particular program.
-
-[While we are at it...  Many people wish we could have "object stubs"
-as well, so that a table could be defined and redefined without having
-to recompile the spec where the table is declared.]
-
-*************************************************************
-
-From: Randy Brukardt
-Sent: Monday, September 24, 2001, 7:56 PM
-
-> I like almost everything about this proposal except the syntax
-> (and perhaps the use of the phrase "separate incomplete type"
-> rather than something like "type stub" for the incomplete type).
-
-The reason for calling it an "incomplete type" is so that most of the rules
-that apply to an incomplete type also apply to this type. There are enough
-differences so that it doesn't matter a lot, but the incomplete syntax is
-attractive.
-
-> How about defining a new kind of "representation" clause:
->
->     for <full_type> use type <separate_incomplete_type>;
->
-> This reads better to me.  It also allows us to associate
-> task types and protected types with the separate incomplete type.
-> And it doesn't further muck up the syntax for declaring a type,
-> which is already one of the most nightmarish parts of the
-> Ada grammar.  Clearly this sort of "representation" clause
-> should have to be in the visible part of the package if the
-> connection between the two types is to be visible outside the package.
-
-That would be fine by me, although I'm not certain whether any anomalies are
-introduced by allowing the type declaration and "completion" to be separated.
-(I didn't think about that, 'cause it couldn't happen.)
-
-> One particularly nice feature of this proposal which I didn't
-> realize before is the multiple-implementation concept.  You
-> could have multiple completions of the same type stub, and use
-> a "with" clause on the main subprogram to determine which one
-> gets included in a particular program.
-
-Yes, that seems like another reason to prefer this syntax to the alternative of
-specifying the completor. It probably ought to be mentioned in the AI.
-
-> [While we are at it...  Many people wish we could have "object stubs"
-> as well, so that a table could be defined and redefined without having
-> to recompile the spec where the table is declared.]
-
-Seems like a different kettle of fish; it doesn't have an obvious
-implementation counterpart as incomplete types do. (Restricting such an item
-so that you couldn't use it would work, of course, but seems pointless.)
-
-*************************************************************
-
-From: Tucker Taft
-Sent: Monday, September 24, 2001, 8:52 PM
-
-> The reason for calling it an "incomplete type" is so that most of the rules
-> that apply to an incomplete type also apply to this type. There are enough
-> differences so that it doesn't matter a lot, but the incomplete syntax is
-> attractive.
-
-I wasn't objecting to the word "incomplete" but rather to the
-word "separate".  The other places we use "separate" we
-either use the word "stub" or "subunit," and this use
-clearly corresponds more to the "stub" case.
-
-> ...
->
-> > [While we are at it...  Many people wish we could have "object stubs"
-> > as well, so that a table could be defined and redefined without having
-> > to recompile the spec where the table is declared.]
->
-> Seems like a different kettle of fish; it doesn't have an obvious
-> implementation counterpart as incomplete types do. (Restricting such an item
-> so that you couldn't use it would work, of course, but seems pointless.)
-
-I was more reacting to the fact that extending the notion of "stub"
-from subprograms, packages, tasks, and protected bodies to
-incomplete types made me think about how often I wish I could
-declare an object in a package spec, but define its (static)
-initializers in a separate compilation unit.  This is easy to
-do in C, but a pain in Ada.
-
-*************************************************************
-
-From: Christoph Grein
-Sent: Tuesday, September 25, 2001, 1:10 AM
-
-I'm not sure that I haven't missed something in the proposal.
-What about multiple completions in one program?
-
-   with XXX_Interface;
-   package XXX_Completion is
-     type T for XXX_Interface.T is tagged private;
-     ...
-   end XXX_Completion;
-
-   with XXX_Interface;
-   package Another_XXX_Completion is
-     type T for XXX_Interface.T is tagged private;
-     ...
-   end Another_XXX_Completion;
-
-Should there be a rule making a program illegal if there are two completions
-at  the same time?
-
-   with XXX_Completion, Another_XXX_Completion;  -- Compile time error here?
-   package ZZZ is ...
-
-This need not even be within the same unit, but could be in separated parts
-of a program:
-
-   with XXX_Completion;
-   package P1 is ...       -- OK
-
-   with Another_XXX_Completion;
-   package P2 is ...       -- OK
-
-   with P1, P2;            -- Compile time error here?
-   procedure Proc is ...
-
-   with Q1, Q2;            -- Compile time error here? Somewhere in the Q1
-   procedure Qroc is ...   -- tree, P1 is "withed", the same for Q2 and P2.
-
-Or would these be link-time errors?
-
-And what about partitions having different completions?
-
-*************************************************************
-
-From: Tucker Taft
-Sent: Tuesday, September 25, 2001, 8:34 AM
-
-Christoph Grein wrote:
->
-> I'm not sure that I haven't missed something in the proposal.
-> What about multiple completions in one program?
-
-The rule was there, albeit a bit cryptic:
-
-    ... There is a post compilation rule that a separate
-    incomplete type may have only a single completion.
-
-I presume the rule when written out in its entirety would make
-it clear that at most one completion would be allowed in a
-single partition.  I would think it would be OK if different
-completions were used in different partitions of the same
-program, so long as the type is not a "remote" type.  But
-clearly some more thought is needed to understand all the
-implications for a distributed program...
-
-> ...
-> Or would these be link-time errors?
-
-That's what the phrase "post compilation" means (at least
-to language lawyers ;-).
-
-
-> And what about partitions having different completions?
-
-Good question.  Should probably be legal except where
-it causes problems (so what else is new?).
-
-*************************************************************
-
-From: Simon Wright
-Sent: Tuesday, September 25, 2001, 3:58 AM
-
-The code below is my understanding of how what I'm presently doing
-with GNAT's version of WITH TYPE might appear under the proposed
-scheme. Have I got the right end of the stick?
-
-The thing that causes GNAT most trouble appears to be the Storage_Size
-rep clause (I understand Storage_Pool would be problematic too).
-
-  package Department_Interface is
-     type Handle is separate;
-  end Department_Interface;
-
-  package Employee_Interface is
-     type Handle is separate;
-  end Employee_Interface;
-
-  with Department_Interface;
-  with Employee_Interface;
-  package Employee is
-     type Instance (<>) is limited private;
-     type Handle for Employee_Interface.Handle is access Instance;
-     ...
-  private
-     type Instance is record
-	...
-	Dept : Department_Interface.Handle;
-	...
-     end record;
-     for Handle'Storage_Size use ...;
-     ...
-  end Employee;
-
-*************************************************************
-
-From: Randy Brukardt
-Sent: Tuesday, September 25, 2001, 11:34 AM
-
-It's not quite right, because you can't declare an object or component of an
-incomplete type. So the component declaration "Dept" is illegal.
-
-See the example in the AI for an example of how to do it. The basic idea is to
-move the access type handle to the interface package. Because that is a normal
-type, you can give the 'Storage_Size or 'Storage_Pool clause there.
-
-That is, a "with type" becomes a incomplete stub (separate incomplete, I used
-Tucker's suggested terminology here); a "with type access" becomes an access to
-an incomplete stub.
-
-> The thing that causes GNAT most trouble appears to be the Storage_Size
-> rep clause (I understand Storage_Pool would be problematic too).
-
-Right. That was the main reason that "with type access" was dropped from the
-"with type" proposal, and eventually, we started looking for alternatives.
-
-*************************************************************
-
-From: Simon Wright
-Sent: Wednesday, September 26, 2001, 4:12 AM
-
-OK, but I get the feeling that the part of the 'Storage_Size clause I
-left out is going to be illegal now -- it does depend on a
-GNAT-specific attribute.
-
-  package Department_Interface is
-    type Instance (<>) is separate;
-    type Handle is access Instance;
-    for Handle'Storage_Size use (Instance'Object_Size * 42) / 8;
-    --  there are only ever going to be 42 Instances at once
-    --  8-bit bytes here
-  end Department_Interface;
-
-The point of this manoeuvre is to avoid malloc/free in a VxWorks
-context. Clearly I could allocate all the Instances I'm going to need
-at initialization, or use a special storage pool which is initialized
-after I know Instance'Size, or manage a static array, or ...; it
-seemed better to use a language mechanism where possible.
-
-*************************************************************
-
-From: Randy Brukardt
-Sent: Wednesday, September 26, 2001, 11:13 AM
-
-You're right, the use of the name "Instance" in the attribute is illegal by the
-rules in 3.10.1.
-
-One point that is important to note that your original example couldn't be
-written in ANY of the proposals that the ARG is looking at; they all have
-incomplete type restrictions on the type. (Private types aren't allowed in
-package abstracts because of the freezing rules - I believe that is
-intentional.)
-
-> The point of this manoeuvre is to avoid malloc/free in a VxWorks
-> context. Clearly I could allocate all the Instances I'm going to need
-> at initialization, or use a special storage pool which is initialized
-> after I know Instance'Size, or manage a static array, or ...; it
-> seemed better to use a language mechanism where possible.
-
-Another way to structure your code would be to use an incomplete deferred to
-the body (to allow the component declaration), but that still wouldn't allow
-the use of the 'Object_Size attribute.
-
-After all, the entire point of this mechanism (or any of the others) is to
-allow you to use a type without knowing much about it - representation, size,
-etc. It seems wrong to then turn around and try to find out that information.
-The only way to support this would be to totally abandon the requirement to
-see the full type before using a partial view -- which would be a giant change
-in the Ada model and clearly would have a large impact on implementations. That
-seems to be much too big a change for Ada.
-
-*************************************************************
-
-From: Tucker Taft
-Sent: Wednesday, September 26, 2001,  1:43 PM
-
-Simon wrote:
-
-> > OK, but I get the feeling that the part of the 'Storage_Size clause I
-> > left out is going to be illegal now -- it does depend on a
-> > GNAT-specific attribute.
-
-'Size would almost certainly work just as well as 'Object_Size presuming
-you are allocating composite objects.  But the big problem is that
-the compiler doesn't know anything about Instance, so 'Size or 'Object_Size
-pretty much has to be illegal on a type stub.
-
-> >   package Department_Interface is
-> >     type Instance (<>) is separate;
-> >     type Handle is access Instance;
-> >     for Handle'Storage_Size use (Instance'Object_Size * 42) / 8;
-> >     --  there are only ever going to be 42 Instances at once
-> >     --  8-bit bytes here
-> >   end Department_Interface;
-
-One alternative would be to make this a general access type (... access all ...)
-and have a separate access type (collection) which is used for all
-allocators, and then convert the result of the allocator to the "visible"
-access type declared in Department_Interface.  The access type
-used for allocators could be declared at a point that had visibility
-on the full type definition of "Instance."  In my experience, a much
-smaller portion of the code needs to be able to do allocators than needs
-to be able to reference the access type.
-
-*************************************************************
-
-From: Simon Wright
-Sent: Thursday, September 27, 2001, 3:22 AM
-
-Randy said:
-
-> Another way to structure your code would be to use an incomplete
-> deferred to the body (to allow the component declaration), but that
-> still wouldn't allow the use of the 'Object_Size attribute.
-
-Thanks to you and Tuck for the suggestions, I'll need some time to
-digest them!
-
-> After all, the entire point of this mechanism (or any of the others)
-> is to allow you to use a type without knowing much about it -
-> representation, size, etc. It seems wrong to then turn around and
-> try to find out that information. The only way to support this would
-> be to totally abandon the requirement to see the full type before
-> using a partial view -- which would be a giant change in the Ada
-> model and clearly would have a large impact on implementations. That
-> seems to be much too big a change for Ada.
-
-Point taken.
-
-*************************************************************
-
-From: Dan Eilers
-Sent: Thursday, September 27, 2001, 12:23 PM
-
-> OK, but I get the feeling that the part of the 'Storage_Size clause I
-> left out is going to be illegal now -- it does depend on a
-> GNAT-specific attribute.
->
->   package Department_Interface is
->     type Instance (<>) is separate;
->     type Handle is access Instance;
->     for Handle'Storage_Size use (Instance'Object_Size * 42) / 8;
->     --  there are only ever going to be 42 Instances at once
->     --  8-bit bytes here
->   end Department_Interface;
-
-Perhaps a solution to this would be to extend the standard attribute
-S'Max_Size_In_Storage_Elements (see RM 13.11.1), so that it can be applied
-directly to an access type, instead of only to a subtype designated by an
-access type.
-
-This eliminates the problem Randy pointed out, where RM 3.10.1 (5-9)
-precludes most usages of incomplete types.
-
-Of course, the amount of storage needed will not be statically known at
-the point of the storage_size attribute definition clause, but this clause
-does not require a static expression.
-
-Are there elaboration order concerns that would preclude this solution?
-The amount of storage needed would probably have to be pre-elaborable.
-
-Then this could be written as:
-
-  package Department_Interface is
-    type Instance (<>) is separate;
-    type Handle is access Instance;
-    for Handle'Storage_Size use (Handle'Max_Size_In_Storage_Elements * 42);
-    --  there are only ever going to be 42 Instances at once
-  end Department_Interface;
-
-Note that this happens to also eliminate the "/ 8".
-
-*************************************************************
-
-From: Dan Eilers
-Sent: Thursday, September 27, 2001, 12:37 PM
-
-Tuck wrote:
-> Christoph Grein wrote:
-> >
-> > I'm not sure that I haven't missed something in the proposal.
-> > What about multiple completions in one program?
->
-> The rule was there, albeit a bit cryptic:
->
->     ... There is a post compilation rule that a separate
->     incomplete type may have only a single completion.
->
-> I presume the rule when written out in its entirety would make
-> it clear that at most one completion would be allowed in a
-> single partition.  I would think it would be OK if different
-> completions were used in different partitions of the same
-> program, so long as the type is not a "remote" type.  But
-> clearly some more thought is needed to understand all the
-> implications for a distributed program...
-
-Randy wrote:
->         I followed Pascal's lead, and only put in restrictions where they
-> were necessary for consistency, semantic, or implementation reasons.
-
-It would be useful to specify the reason for the above rule.
-Is it necessary for type safety, as claimed in:
- http://home.bluemarble.net/~jvolan/WithingProblem/FAQ.html#forward_incompletes
-
-*************************************************************
-
-From: Randy Brukardt
-Sent: Monday, October 1, 2001,  7:28 PM
-
-Dan said (talking about the postcompilation rule for a single completion):
-
-> It would be useful to specify the reason for the above rule.
-> Is it necessary for type safety, as claimed in:
-> http://home.bluemarble.net/~jvolan/WithingProblem/FAQ.html#forward_incompletes
-
-I mentioned the reason in e-mail (see the appendix of the AI) back in July, and
-it seemed so obvious that I didn't mention it. Essentially it is necessary to
-have only a single completion in a partition, because otherwise you could use
-one completion as the other without any warning:
-
-    package Interface is
-       type Stub is tagged separate;
-    end Interface;
-
-    with Interface;
-    package Complete1 is
-       type Tag1 for Interface.Stub is tagged record
-          F : Float;
-       end record;
-    end Complete1;
-
-    with Interface;
-    package Complete2 is
-        type Tag2 for Interface.Stub is tagged record
-           I : Integer;
-        end record;
-    end Complete2;
-
-    with Interface;
-    procedure Do_Something (A : in Interface.Stub);
-
-    with Interface, Complete1;
-    procedure Do_Something (A : in Interface.Stub) is
-    begin
-       if A.F = 1.0 then -- (1)
-       ...
-    end Do_Something;
-
-    with Interface, Complete2, Do_Something;
-    procedure Problem is
-       T : Complete2.Tag2;
-    begin
-	 Do_Something (T); -- (2)
-    end Problem;
-
-Assume that multiple completions are allowed. The call at (2) is legal, as
-Interface.Stub is a subtype of Complete2.Tag2 in Problem (as the completion is
-visible). The reference to component F at (1) is also legal, because
-Interface.Stub is a subtype of Complete1.Tag1 in Do_Something (again the
-completion is visible). But we passed a Tag2 object to Do_Something, which then
-proceeds to use it as a Tag1 object (reading an Integer as a Float, or worse).
-Obviously, we can't allow that.
-
-The easiest way to solve this problem is to disallow multiple completions in a
-single partition, and it doesn't seem to be an important capability. I suspect
-that the rule really has to be program (allowing different completions in
-different partitions of the same program would allow the same problem to occur
-across partitions -- which probably would be worse than the problem in a single
-partition).
-
-*************************************************************
-
-From: Dan Eilers
-Sent: Thursday, September 27, 2001, 2:00 PM
-
-Tuck wrote:
-
-> How about defining a new kind of "representation" clause:
->
->     for <full_type> use type <separate_incomplete_type>;
->
-> This reads better to me.  It also allows us to associate
-> task types and protected types with the separate incomplete type.
-> And it doesn't further muck up the syntax for declaring a type,
-> which is already one of the most nightmarish parts of the
-> Ada grammar.  Clearly this sort of "representation" clause
-> should have to be in the visible part of the package if the
-> connection between the two types is to be visible outside the package.
-
-Would it make sense to allow an ordinary incomplete type to
-be completed in this way as well?
-
-Note: this is getting pretty close to type renaming.
-
-*************************************************************
-
-From: Tucker Taft
-Sent: Thursday, September 27, 2001,  3:27 PM
-
-I'm not sure.  It's actually a bit misleading to call it
-"completing" the incomplete type.  The incomplete type
-is effectively becoming a subtype of the full type.
-Perhaps that is the syntax we should use instead?  E.g.:
-
-    separate subtype P.Type_Stub is Full_Type;
-
-This would nicely generalize for "regular" incomplete types
-to be "completed" by a subtype declaration.
-
-    subtype Inc_Type is Whatever.Some_Full_Type;
-
-I'm not sure what particular benefit this would provide,
-because presumably the primitive operations of the
-type are *not* made visible by this subtype declaration.
-
-Actually, if we are willing to consider going back to the
-new-kind-of-compilation-unit, then the correct syntax for
-completing a type stub would be a separate compilation unit:
-
-    with Z;
-    separate (P)
-    subtype Type_Stub is Z.Full_Type;
-
-This would actually be the most consistent with existing stub
-completion syntax.  The special rule is that this (sub)type "subunit"
-would *not* be substituted into the point of the "stub" unless
-the subunit is somehow made visible in a context clause.  And how
-do we make the type subunit visible?  Well of course...
-
-
-   [drum roll...]
-
-
-    with type P.Type_Stub;
-
-[I can hear the worldwide groans from here ;-]
-
-> Note: this is getting pretty close to type renaming.
-
-I guess, though it seems somewhat upside down.  Sort of
-the "come-from" of the renaming world ;-).  I suppose
-the real question is whether the primitive operations
-of a type stub are implicitly declared (or implicitly
-renamed?) at the point of the stub, when the completion
-of the stub (whatever syntax that ends up using) is visible.
-
-Randy, did you cover this issue of primitive operation
-implicit declaration/renaming?
-
-Any comments on using a subtype declaration-ish syntax
-for "completing" a type stub, either as a declaration
-within some package spec, or as a separate "type subunit"
-compilation unit?
-
-Actually, if we really give these things subtype-like
-equivalence, perhaps we should allow the "is separate"
-syntax on a subtype declaration only?  And similarly,
-use an "incomplete subtype" if we want to complete
-the declaration using a subtype declaration.  E.g.:
-
-    subtype Subtype_Stub is separate;
-      -- declare a subtype "stub"
-  or
-    subtype Incomplete_Subtype;
-      -- declare an incomplete subtype
-
-*************************************************************
-
-From: Dan Eilers
-Sent: Friday, September 28, 2001, 2:31 PM
-
-I think the "separate incomplete" proposal comes real close to
-this, if one puts the full type definition in a child unit
-(with the incomplete type in the package spec).
-Then, instead of needing a new kind of compilation unit for
-a separate subtype, a normal child unit works.  And instead
-of needing a new type of "with" clause, a normal "with" of the
-child unit works.
-
-*************************************************************
-
-From: Randy Brukardt
-Sent: Monday, October 1, 2001,  7:44 PM
-
-Tuck said:
-
->    [drum roll...]
->
->
->     with type P.Type_Stub;
->
-> [I can hear the worldwide groans from here ;-]
-
-I certainly groaned at this whole line of thought. If we're going to bother
-with a new kind of compilation unit, we might as well go with the package
-abstracts. The whole point of incomplete stubs is that we don't need a bunch of
-heavy new mechanisms to solve the problem.
-
-> I guess, though it seems somewhat upside down.  Sort of
-> the "come-from" of the renaming world ;-).  I suppose
-> the real question is whether the primitive operations
-> of a type stub are implicitly declared (or implicitly
-> renamed?) at the point of the stub, when the completion
-> of the stub (whatever syntax that ends up using) is visible.
->
-> Randy, did you cover this issue of primitive operation
-> implicit declaration/renaming?
-
-I didn't "cover it", because I intended that no such thing would happen. I
-selected "subtype" specifically because I didn't want to deal with primitive
-operations. (Note that a regular incomplete type has no primitive operations of
-its own; the problem occurs with tagged incomplete types, which allow
-parameters of the type). Certainly, we want the primitive operations to be
-declared with the full type. I guess I'd prefer that the incomplete stub had no
-primitive operations by itself; we'd have to add a rule saying that there are
-no such things. (You can't derive from the incomplete type anyway.) When it is
-completed and is acting as a subtype, it is of course the same as the
-completing type.
-
-> Any comments on using a subtype declaration-ish syntax
-> for "completing" a type stub, either as a declaration
-> within some package spec, or as a separate "type subunit"
-> compilation unit?
-
-I'm not against the subtype syntax for a completion; it is, after all, exactly
-what the semantics are. I like that better than the representation clause
-syntax.
-
-> Actually, if we really give these things subtype-like
-> equivalence, perhaps we should allow the "is separate"
-> syntax on a subtype declaration only?  And similarly,
-> use an "incomplete subtype" if we want to complete
-> the declaration using a subtype declaration.  E.g.:
->
->     subtype Subtype_Stub is separate;
->       -- declare a subtype "stub"
->   or
->     subtype Incomplete_Subtype;
->       -- declare an incomplete subtype
-
-That is possible, but then of course we'd have to define these things
-separately from existing incomplete types. That's not necessarily a bad idea
-(it avoids the primitive operations problem noted above cleanly), but it does
-increase the "weight" of the solution a bit.
-
-*************************************************************
-
-From: Dan Eilers
-Sent: Tuesday, October 2, 2001,  1:37 PM
-
-Would the type safety problems associated with multiple bindings
-of type stubs be avoided by prohibiting the use of the type stub
-as anything other than a stub, even after being bound?
-If so, this would eliminate the need for cumbersome post-compilation
-rules attempting to prevent multiple bindings across independent
-partitions within a program.
-
-Slightly modifying Randy's example where noted:
-
-    package Interface is
-       type Stub is tagged separate;
-    end Interface;
-
-    with Interface;
-    package Complete1 is
-       type Tag1 for Interface.Stub is tagged record
-          F : Float;
-       end record;
-    end Complete1;
-
-    with Interface;
-    package Complete2 is
-        type Tag2 for Interface.Stub is tagged record
-           I : Integer;
-        end record;
-    end Complete2;
-
-    with Interface;
-    procedure Do_Something (A : in Interface.Stub);
-
-    with Interface, Complete1;
--- (A : in Interface.Stub) is
-    procedure Do_Something (A : in Complete1.Tag1) is  -- conformant
-    begin
-       if A.F = 1.0 then -- (1)
-       ...
-    end Do_Something;
-
-    with Interface, Complete2, Do_Something;
-    procedure Problem is
-       T : Complete2.Tag2;
-    begin
-         Do_Something (T); -- (2)  -- compile-time type clash: Tag2 vs. Tag1
-    end Problem;
-
-*************************************************************
-
-From: Gary Dismukes
-Sent: Tuesday, October 2, 2001,  2:29 PM
-
-I don't see how that would help.  You're generally going to want to
-have access types that designate the stub type, and there's no way
-of preventing accesses from denoting objects of differing full types
-if you allow multiple full types.  The limitation to one full type
-per type stub is a fundamental restriction as far as I can see.
-
-*************************************************************
-
-From: Randy Brukardt
-Sent: Tuesday, October 2, 2001,  2:24 PM
-
-That was my original idea. But the rules for doing that are rather messy, and
-it makes these very much harder to use, so I abandoned it. (Note that the
-original name of the AI mentioned in the agenda is "forever incomplete types").
-
-Among other things, we would have to invent a series of horrible type
-conversion rules (in that model, the incomplete type has to be a completely
-separate type); to make this work reasonably, they have to be implicit
-conversions. Worse, it means that an access type which designates a separate
-incomplete type could never have an allocator (as there would be no place where
-such an allocator could be used). And that means that users would have to use
-explicit conversions (or 'Access, they're equivalent) to use such a type. That
-is one of the major reasons that "with type" was abandoned, and I was quite
-unwilling to introduce it into this proposal.
-
-No matter what the model, it's important to remember that "separate incomplete
-types" or whatever they end up being called need to be usable. Restrictions on
-the use of the type certainly harm the usability.
-
----
-
-In your example:
-
-    with Interface;
-    procedure Do_Something (A : in Interface.Stub);
-
-    with Interface, Complete1;
--- (A : in Interface.Stub) is
-    procedure Do_Something (A : in Complete1.Tag1) is  -- conformant
-    begin
-       if A.F = 1.0 then -- (1)
-       ...
-    end Do_Something;
-
-    with Interface, Complete2, Do_Something;
-    procedure Problem is
-       T : Complete2.Tag2;
-    begin
-         Do_Something (T); -- (2)  -- compile-time type clash: Tag2 vs. Tag1
-    end Problem;
-
-I don't see why you'd have a type clash here: the specification of Do_Something
-clearly specifies Stub, which has to match either type. Without seeing the
-body, you don't know which is meant. Surely you can't be suggesting some sort
-of body dependence; it is too much dependence that we are trying to get away
-from (keep in mind that Do_Something could have been defined in Interface
-itself, and a body dependence then would essentially reintroduce the problem
-we're trying to get around).
-
-*************************************************************
 

Questions? Ask the ACAA Technical Agent