CVS difference for ais/ai-30217.txt
--- ais/ai-30217.txt 2002/02/20 01:04:09 1.2
+++ ais/ai-30217.txt 2002/03/13 00:48:29 1.3
@@ -1,345 +1,353 @@
-!standard 03.10.01 (02) 02-02-06 AI95-00217-04/01
+!standard 03.10.01 (02) 02-03-01 AI95-00217-04/02
!class amendment 02-02-06
!status work item 02-02-06
!status received 02-02-06
-!subject Handling mutually recursive types via separate incomplete types with package specifiers
+!subject Handling mutually recursive types via type stubs with package specifiers
-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-01,
-the "package abstract" proposal of AI-217-02, and the initial proposal for
-separate incomplete types in AI-217-03.
-A separate incomplete type is an incomplete type which is completed in
-another package. Where the type is to be regarded as completed and where
-it is incomplete, subject to all the restrictions of incomplete types,
-is discussed in !discussion. << A final resolution will go here :-)
-Preliminary investigation says that it cannot be based on visibility !>>
-As the added capability is primarily targeted at mutually recursive
-tagged types, for which it is important that the incomplete separate
-type be allowed in the parameter profile of primitive operations, a
-capability is added to declare the imcomplete type to be a tagged
-type. For such tagged incomplete types, the respective restriction for
-incomplete types is eliminated.
-The separate incomplete type identifies the package in which the
-completion is to occur. No semantic dependence on the package is
-created by this identification. In order for a type declaration to be a
-completion of the separate incomplete type declarations, both must
-declare the same identifier and the completing type declaration must
-be in the package identified by the separate incomplete type
-declaration. A completion may not be a incomplete type declaration. A
-tagged incomplete type declaration can only be completed by a tagged
-There may be multiple incomplete type declarations that are completed
-by a single completing type declaration. Note that this is essential
-if separate incomplete types are allowed in generic packages.
+A new construct, called a "type stub," 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-01, the "package abstract" proposal of
+AI-217-02, and the initial proposal for type stubs in AI-217-03. [NOTE: the
+term "separate incomplete type" has been used instead of type stub, but we felt
+it was more consistent to use the term "stub" rather than "separate" to be
+consistent with the program unit "stub" terminology.]
+A type stub is a kind of incomplete type declaration which is completed in
+another (specified) package. The package in which the completion is to occur is
+specified by its full expanded name. No semantic dependence on the package is
+created by this specification. Compile-time checks are performed on use of the
+name introduced by the type stub that the completion is "available" and
+"appropriate" (see !proposal for details).
+A concept of a "tagged incomplete" type is introduced, which is a type that has
+the same restrictions as an incomplete type except that it may also be used for
+a formal or actual parameter. A corresponding tagged type stub is defined,
+with the corresponding restrictions.
-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.
+Ada allows mutually recursive types to be declared only 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.
+primitive operations with (pointers to) each other as parameters), and to do
+this in a way that doesn't place any undue restrictions on the programmer.
+For mutually recursive types, it is valuable if subprogram parameters may be of
+the type itself, rather than only an access to the type. However, for most
+types, it may be necessary to see the full definition to know how parameters of
+the type are passed. However, because tagged types are always passed by
+reference, there is no implementation difficulty in allowing them to be used as
+parameters even when the full definition of the type is not available. Hence,
+it makes sense to relax the rule for using incomplete types that are known to
+be tagged, to allow them as formal and actual parameters, since from a code
+generation point of view they are essentially equivalent to access parameters.
-<<< I may have undone a desirable change, which would allow the good
-old incomplete types to be specified as tagged, with the rules as below.
-I don't recall that discussion, but this change could be easily undone.
-Without this secondary capability, I felt the syntax below to be simpler. >>>
+The syntax for an incomplete type declaration is amended as follows:
-An additional kind of type declaration is proposed:
+ incomplete_type_declaration ::=
+ TYPE defining_identifier [discriminant_part] [IS TAGGED]
+ | type_stub;
+If the words IS TAGGED appear, the type is a tagged incomplete type. Otherwise,
+the type is a non-tagged incomplete type. In addition to places where a
+(non-tagged) incomplete type may be used, a tagged incomplete type may be used
+as a formal parameter type, and an actual parameter that is a dereference of an
+access-to-tagged-incomplete value. The attribute 'Class is defined for
+(specific) tagged incomplete types. (The use of 'Class with non-tagged
+incomplete types is considered obsolescent.) The class-wide type denoted by the
+Class attribute of an incomplete tagged type is also an incomplete tagged type.
+An incomplete tagged type declaration must be completed by a tagged type
- separate_type_declaration ::=
+An additional kind of incomplete type declaration is proposed:
+ type_stub ::=
TYPE defining_identifier [discriminant_part]
- IS [ TAGGED ] SEPARATE IN package_name;
+ IS [ TAGGED ] SEPARATE IN package_specifier;
+ package_specifier ::=
+ | package_specifier . identifier;
-A separate_type_declaration introduces an incomplete type whose
-completion occurs in another package identified by the package_name.
+A type_stub introduces an incomplete type whose completion occurs in another
+package identified by the package_specifier. If the word TAGGED appears, the
+type is a tagged incomplete type.
-The specified package_name is neither subjected to the name resolution
-rules at the place of the separate_type_declaration, nor does it create a
-semantic dependency on the named package. [Rather than introducing this
-special rule of not interpreting the name at this place, the
-language-lawyerly approach would be to syntactically include the
-package name by means of a string_literal. This, however, is not
-user-friendly because of the quotes and the lack of a syntax check on
-the package name.]
-A separate type whose declaration contains 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. 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.)
-In order to be a completion, the completing type declaration must be
-in the visible part of the package identified by the incomplete type
-declaration, must not be an incomplete type declaration, and must
-satisfy all other rules for type completion. This rule is enforced
-when << fill in the resolution after discussion >>.
-There may be multiple incomplete type declarations that are completed
-by a single completing type declaration. Note that this is essential
-if separate incomplete types are allowed in generic packages.
-The restricting rules on the use of incomplete types apply to separate
-types. The separate type is completed at places that semantically
-depend on the unit containing the completion. The usual visibility rules
-apply to the operations on the type, which are declared together with the
+The package_specifier is neither subjected to the name resolution rules at the
+place of the type_stub, nor does it create a semantic dependence on the
+In order to be a completion, the completing type declaration must be in the
+visible part of the package identified by the type stub, must not be an
+incomplete type declaration, and must satisfy all other rules for incomplete
+type completion. This rule is enforced when the incomplete type is used in a
+context where a complete type is required.
-There seem to be two general ways the problem of mutually recursive
-types 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.
+When the name introduced by a type stub is used in a context where it must
+match some other type, if the other type is a type stub, a check is made they
+have the same package specifier. If the other type is a complete type, a check
+is made that the the full expanded name of the package where the other type is
+declared matches that of the type stub's package specifier, and the other type
+can be a completion of the incomplete type.
-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.
+When a name introduced by a type stub is used in a context where a complete
+type is required, other than where it must match a particular complete type
+(which is described above), a check is made that the usage place is within the
+immediate scope of the completion, or is within the scope of a with clause that
+mentions the package identified by the type stub's package specifier. A check
+is made that the completion is not an incomplete type declaration, and
+satisfies the other requirements for completing an incomplete type. A check is
+made that the package_specifier provides the full expanded name of the
+completing package -- it must not involve any renamings. (This eliminates
+ambiguities when checking for type matching of two type stubs with the same
+completion, and simplifies the check whether a completing package is
-The model of a separate incomplete type per se does not add any new
-implementation burden, because it is very similar to the
-incomplete-deferred-to-body type which Ada 95 already has. The compiler does
-not need to know the real type involved as long as the usage rules for
-incomplete types 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 for a type whose completion
-is deferred to the body. 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.
-Conceptual and implementation dificulties arise from the question where the
-type is to be regarded as completed and hence allows for object creation and
-availability of operations of the type. It is clear that such a place must have
-a semantic dependence on (the package containing) the type completion.
-Two issues remain:
-1. when does the checking take place to ensure that a type declaration is a
- legal completion for the incomplete type declaration (and how is the
- correlation specified) ?
-2. independent of 1), the implementation will have to take special action to
- ensure that in places where the incomplete type is to be regarded as
- completed, the incomplete type declaration is "tied" to its completion.
-On issue 1) there are three approaches conceivable:
-a) The completing declaration identifies the declaration it completes. The
- conformance check occurs at this point. This is the approach of AI-277.
- While simple at first glance, it has serious disadvantages:
- - the type declaration syntax is already "heavy"; adding more options
- to the syntax of full type declarations is not advisable.
- - to perform the check, a semantic dependence on the package containing
- the incomplete type needs to be created. In simple cases of breaking
- but one mutual recursion of types across two packages, this may be
- acceptable. In cases involving multiple packages, it may be difficult
- to find a suitable and maintainable hierarchy (without introducing
- artificial connector packages).
- - because of this requirement, incomplete types cannot be sensibly
- used in generic packages. (Which instantiation does the completor
- refer to ?)
- - clearly, a post-compilation check is needed to prevent multiple,
- different completions in a partition.
- - also, a rule is needed that prevents multiple completions
- in the semantic closure of a compilation. It is not clear (to the
- author) how such a rule could be formulated without causing
- significant implementation burden.
- - the implementation effort to solve issue 2 is required regardless.
-b) The incomplete declaration identifies the expected place of the
- completion. Then, for any unit that has a semantic dependence on the
- incomplete type and also on the package containing its completion,
- the completion check and the implementation "tie-in" is made prior to
- compiling the unit at hand. (Compilations that depend on only one of
- the two units obey the usual rules of incomplete, resp,. full type
- declarations.) See, however, some further discussion below.
-c) The incomplete declaration identifies the expected place of the
- completion. Any operation involving the incomplete type that normally
- would require prior completion of the type is combined with the
- completion check (and the creation of the necessary "tie-in").
-A concern is that a legal unit depending (only) on the package with
-the completing type declaration remain legal when an "extraneous"
-with-clause in another package is subsequently added and establishes a
-semantic dependence on the package containing the incomplete
-type. (Removal of a with-clause, on the other hand, is not a problem.)
-Thus, the rule should not be based on the semantic dependence concept.
-Here is an example that illustrates the issue:
+ incomplete_type_declaration ::= TYPE defining_identifier [discriminant_part] [IS TAGGED];
+ | type_stub
-package P is
- type T is record Comp:integer; end record;
+ type_stub ::= TYPE defining_identifier [discriminant_part] IS [TAGGED]
+ SEPARATE IN package_specifier;
-package Q is
- Obj: aliased P.T;
-package X is
- type T is tagged separate in P;
+ package_specifier ::= identifier | package_specifier . identifier
-[with X;] -- originally not there
-package Y is ...
-with Y, Q;
-procedure Test is
- Q.Obj.Comp := 5;
+ An incomplete_type_declaration other than a type_stub requires a
+ completion, which ...
-Without the with-clause in question, this is clearly legal. Note
-that P.T is NOT visible in Test (and yet operations on T are legal).
-It is arguable whether the (failing) conformance test on the separate
-type should be performed in Test when the with-clause has been added.
-If it is performed, it leaves the worry about ripple effects of
-extraneous with-clauses. If it is not performed, then semantic
-dependence alone cannot be cause for the check.
-Now consider a slight change to the example:
-package X is
- type T is separate in P; -- removed the offending "tagged"
-package Y is
- type T_Acc is access all X.T;
-with Y, Q;
-procedure Test is
- A := Q.Obj'Access;
+ A type_stub includes a package_specifier which specifies the full
+ expanded name of the package in which its completion is expected to
+ occur. Certain uses (see below) of a name that denotes the type_stub or
+ a value of an access type that designates the type stub, require that
+ the completion exist. In these cases, the completion shall occur in the
+ visible part of the specified package, and be a type_declaration other
+ than an incomplete_type_declaration; the package_specifier shall be the
+ full expanded name of this package (starting with a root library unit,
+ and using no renaming declarations), and the package shall be a library
-Note that neither P.T nor X.T are visible. Here, clearly the check
-needs to be performed and the "tie-in" must happen or else the legality
-of the assignment will not be realized.
-Conclusion: Visibility of the type declaration(s) per se is the wrong
-We could, of course, force the user by special semantic rule to create
-visibility, whenever there is a need for completion. But how to tell
-the user precisely when (s)he needs to create such visibility ? It's
-a non-trivial list, see below, and the compiler might as well figure it
-out silently. Also, as a minor point, what about
-with P, X; -- imported for many other reasons
-procedure Test is
-begin -- no mention of T anywhere
-Should correspondence be checked, even though the common visibility is
+ Add a new first sentence:
-with Y, Q, P; -- slight revision of the 2. example; P now visible
-procedure Test is
- Q.Obj.Comp := 5;
+ If an incomplete_type_declaration includes the word TAGGED, then a
+ type_declaration that completes it shall declare a tagged type.
+ Replace all occurrences of "full_type_declaration" with "type_declaration" in the remaining
+ A name that denotes an incomplete_type_declaration may be used as
+ * as the subtype_mark in the subtype_indication of an
+ access_to_object_definition; the only form of constraint allowed in
+ this subtype_indication is a discriminant_constraint;
+ * as the subtype_mark defining the subtype of a parameter or result of
+ an access_to_subprogram_definition;
+ * as the subtype_mark in an access_definition;
+ A name that denotes an incomplete_type_declaration that includes the
+ word TAGGED may also be used as follows:
+ * as the subtype_mark defining the subtype of a parameter in a
-Should correspondence be checked, although X is not visible but
-semantically depended on ?
+ * as the prefix of an attribute_reference whose attribute_designator is
+ Class; such an attribute_reference is restricted to the uses allowed
-... more variations of the theme, but it becomes boring....
+[NOTE: I have moved the allowance for 'Class after a non-tagged incomplete type
+to Annex J. See below.]
-And so we turn to the third model.
+ If a name that denotes an incomplete_type_declaration is used in other
+ contexts, the incomplete_type_declaration shall be a type_stub, and the
+ completion shall be *available* at the place of use, as defined by
+ either of the following conditions:
-With Visibility awkward and Semantic Dependence somewhat dubious (the
-author actually doesn't think too badly about it despite the ripple),
-the obvious route is to explore a "check-as-needed" model, i.e.,
-whenever an operation is attempted that involves both the complete and
-the incomplete type, the check is performed. These operations are:
- - dereferencing on access types with the incomplete type as target
- - assignment and comparison of such access types
- - parameter matching with tagged incomplete types for formals
- - access-to-subprogram matching involving such types for formals or result
- - <<< others ? >>>
-These checks are automatic - no need to complicate the language...other
-than saying after the "shall match" rule that the rule is enforced
-any time an operation is attempted that involves both the incomplete and
-the completing type.
-Beyond the "when" of the check, we need to specify more clearly the
-"what" of the check.
-We propose the following:
-The name specified in the package_name of the separate_type_declaration must
-be the name of a package in the environment. The named package must either
-be a root package or a child package. In the case of a private child package,
-the package containing the separate incomplete type declaration must be
-a private descendant of the direct parent unit of the child unit. In the
-case of a non-private child package, the package containing the separate
-incomplete type declaration must be a descendant of any private parent
-unit of the child unit.
-(Note that there are no remnants of "order" within Standard in these rules,
- i.e., of the visibility model, so that forward references are truly allowed
- and there is no question about local homographs, etc.
- We do guarantee the privateness rules, however.)
-The completing type declaration must be a full type declaration in the
-visible part of the package [this could be extended to private parts
-for the case where the other package is a private child, but I don't
-think this is worth it] and must declare a type with the same
-Whether or not the package name may involve renamings is debatable. The
-issue is not essential to the proposal. Arguments should be heard on the
-subject. (The author's opinion is to allow renamings, since the restriction
-is hard to sell to users who like to abbreviate their "working set" of
-We propose to allow 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.) As an added
-benefit to implementers, the need for a post-compilation check is avoided.
+ * the place of use is within the immediate scope of the completion of
+ the type_stub; or
+ * the place of use is within the scope of a with_clause that mentions
+ the package specified by the package_specifier of the type_stub.
+ The completion of an incomplete_type_declaration that is not a
+ type_stub is defined to be *available* throughout the (extended) scope
+ of the completion. The completion of an incomplete class-wide type is
+ *available* wherever the completion of the root of the class is
+ A dereference (implicit or explicit) of a value of an access type whose
+ designated type D is incomplete is allowed only in the following
+ * in a place where the completion of D is available (see above);
+ * in a context where the expected type is E and
+ o E is the same as D or its completion, or
+ o E is the same as D'Class or its completion, or
+ o E'Class is the same as D or its completion;
+ * as the target of an assignment_statement where the type of the value
+ being assigned is V, and V or V'Class is the completion of D.
+ In these contexts, the incomplete type is considered the same type as
+ its completion, and its first subtype statically matches the first
+ subtype of its completion.
+ An incomplete_type_declaration declares an incomplete type and its
+ first subtype; the incomplete type is tagged if the word TAGGED
+ appears; the first subtype is unconstrained if a
+ known_discriminant_part appears. The incomplete type is a type stub if
+ the word SEPARATE appears. Two type stubs are considered the same type
+ if they have the same defining identifier and same sequence of
+ identifiers in their package_specifiers; their first subtypes match
+ statically as well.
+ J.10 The Class Attribute of Non-tagged Incomplete Types
+ For the first subtype S of a type T declared by an
+ incomplete_type_declaration that is not tagged and is not a type stub, the
+ following attribute is defined:
+ Denotes the first subtype of the incomplete class-wide type rooted at
+ T. The completion of T shall declare a tagged type. Such an attribute
+ reference shall occur in the same library unit as the
+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.).
+Note that there may be multiple type stubs that are completed by a single
+completing type declaration. This is essential if type stubs are allowed in
+Note that there is no particular restriction on where a type stub may occur,
+unlike the restriction on program unit stubs. In particular, a type stub may
+occur in a declare block, a subprogram body, or anywhere an incomplete type
+declaration may occur. Of course, they are generally only useful if used in a
+place where a separately compiled unit can see the stub as well as the
+completing package, so putting them in a declare block, or a subprogram body
+without any program unit stubs, would not be of any great use.
+There seem to be two general ways the problem of mutually recursive types 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., and is the approach
+adopted here for cross-package mutual recursion.
+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 type stub per se does not add any significant new implementation
+burden, because it is very similar to the incomplete-deferred-to-body type
+which Ada 95 already has. The compiler does not need to know the real type
+involved as long as the usage rules for incomplete types are enforced.
+Determining the representation of an access type that designates a type stub
+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 for a type whose completion is deferred to the body. Such
+implementations must already be able to handle this somehow.
+Since an access type that designates a type stub 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.
+The key difference here from the "with type" proposal is that type stubs, and
+any associated access type declarations, are "real" declarations that can be
+referenced from other packages. A "with type" clause would have had the same
+rules of a "with" clause, which means that they would not be visible to other
+packages. Instead, each package would require its own with type clause, making
+it harder to share access types, and requiring trickier visibility rules to
+deal with "incomplete" packages as well as incomplete types.
+Conceptual and implementation dificulties arise from the question where the
+type is to be regarded as completed and hence allows for object creation and
+availability of operations of the type. It is clear that such a place must have
+a semantic dependence on (the package containing) the type completion. However,
+to avoid ripple effects relating to "indirect" semantic dependences associated
+with "distant" with clauses, we propose that the completion is only "available"
+when within the immediate scope of the completion itself, or the scope of a
+with clause that mentions the completing package. This rule is relaxed when the
+complete type is in the immediate context of the usage (i.e., the incomplete
+type is used in a context where it must match the complete type).
+We considered other rules, such as requiring only semantic dependence (rejected
+due to the ripple effects), or creating an implicit semantic dependence at the
+point of a usage where the completion was needed (rejected due to difficulties
+for some implementations, and loss of visible "documentation" of the
+Another issue was whether the checking should happen at link time, or at any
+time when both the stub and the completing package were both in scope. We
+rejected both of these as they seemed to add complexity, without adding safety.
+Eliminating the link-time check was seen to be useful for testing individual
+subsystems, before an entire system was complete.
+We considered allowing the type stub to specify both the package where the
+completion occurs, and the name of the completing type. A potential syntax was
+"... is separate P.T" as an alternative to, or in addition to "... is separate
+in P". This seemed particularly useful in contexts where one wanted to have
+multiple type stubs in the same context, and type names like "Object" were
+being used consistently in packages. However, it was pointed out that the
+stubs could be placed in sub-packages if necessary to have two declared in the
+same context. This workaround was considered acceptable, and it preserved the
+simplicity of the single "separate in P" syntax.
+We considered having some restriction relating to specifying private child
+packages. However, it was unclear what the rule should be, and there seemed no
+particular benefit in adding the complexity. Clearly if the completion is in a
+private child, only packages that have visibility on that child can make use of
+the completion, and can dereference an access-to-type-stub. But there seems no
+particular harm in allowing the type stub to specify a private child. Without
+actually "looking" at the specified package, it may not be easy to determine
+whether it is a private child. If the check is made at the time of the use of
+the incomplete type, then a somewhat artificial check needs to be made at that
+time that the location of the type stub is inside the subsystem where the
+completing package is visible. An important property is that changing a
+private child, or adding or removing a private child, have no effect outside
+its "subsystem." That remains true even without any additional check, since
+the type stub by itself is legal, it is the usages that would be affected, and
+they would all have to be inside the subsystem. Note that this decision is not
+critical either way. One could add the "artificial" check described above
+without otherwise altering the rest of the proposal.
Here is the classic case of mutual dependence, where an employee
@@ -406,7 +414,7 @@
-[For discussion on the original version of this proposal, see AI-00217-03.
+[For discussion on the original version of this proposal, see AI-00217-03.]
@@ -1447,6 +1455,234 @@
Hence you could write "Y.all" if Y is access-to-incomplete-tagged, but
about all you could do with it would be to pass it as a (non-controlling)
+Draft minutes on AI-00217-04 from the Cupertino ARG meeting, February 10, 2002
+We plunge right into the details of the proposal (and the recent e-mail
+exchanges on it).
+Pascal points out that the Ripple effect is impossible for the Rational Ada
+compiler technology. Implicit visibility is not acceptable either (it is very
+difficult, but not as impossible as a Ripple effect). The group concludes that
+you need a with clause in order to see the completion. This means either an
+enclosing unit, a with, or and inherited with. It does not mean in the semantic
+closure. The wording would be something like "Within the scope of the
+completion or the scope of a with clause for the completion."
+Tucker writes an example of a question that he has:
+package P is
+ type T is tagged separate in Q;
+ procedure Print (X : T);
+ type T_Ptr is access all T;
+procedure Proc (Y : P.T_Ptr) is
+ P.Print (Y.all); -- legal??
+The completion is not visible in Proc; should this call be legal? Tucker argues
+that it should be.
+Tucker proposes that for tagged incomplete, we should allow tagged incomplete
+as an actual parameter. A straw vote on this proposal passes 7-0-2.
+Tucker continues with the example:
+procedure Proc2 (Y : P.T_Ptr; Z : P.T_Ptr) is
+ Z.all := Y.all; -- legal?? - No, requires with Q.
+This requires the package containing the completion to be withed or directly in
+scope. That's because details of the full type are needed to perform the
+package R is
+ A : Q.T;
+with P, R;
+procedure Proc3 (Y : P.T_Ptr) is
+ W : P.T renames Y.all;
+ R.A := Y.all; -- legal?? (Tucker would like this be to legal.)
+Tucker would like this to be legal, because R.A has the type of the completion,
+and thus details of the completion must be available. So there is no
+implementation reason for it to be illegal.
+The term "completion is available" is defined to mean "in scope of with of
+package containing the completion or immediate scope of the completion."
+Steve Baird proposes the rule: "When the completion is available, then the
+incomplete type is just a subtype of the full type." For example:
+package R2 is
+ A : Q.T;
+ procedure Store (I : out Q.T; J : P.T);
+with P, R2;
+procedure Proc4 (Y, Z : P.T_Ptr) is
+ R2.Store (Z.all, Y.all);
+Bob Duff points out that this would reintroduce the ripple effect - because
+adding or removing a with would change the legality of the program. For
+package R3 is
+ type T2_Ptr is access P.T;
+procedure Proc5 is
+ A, B : R3.T2_Ptr;
+ A.all := B.all;
+ -- Legality of this would change if with Q added to R3.
+So Steve's rule is discarded.
+A different rule is proposed: "If you have a P.t and Q.t in a context, the type
+matching is OK if Q.t is indeed the completion of P.t." Note that the "in"
+package name must not be a renaming.
+Another issue is considered (again extending the same example):
+package P2 is
+ type T is tagged separate in Q;
+with P, P2;
+procedure Proc6 is
+ A : P.T; B : P2.T; -- Are these the same?
+After discussion, the group concludes that these should be the same.
+Steve Michell comments that he would like to be able to change the name of the
+type. In a large project, you may need to be able to change the names of the
+things when integrating (in order to meet subsystem specifications).
+He proposes the syntax should be:
+type T is tagged separate Q.T;
+Tucker notes that if both types are named T ('Object' is commonly used), you
+can't declare the both unless you can change the name. But you can use a nested
+package to work around the limitation as noted below:
+package P3 is
+ package Q_Int is
+ type Object is tagged separate in Q;
+ end Q_Int;
+ package R_Int is
+ type T is tagged separate in R;
+ end R_Int;
+Perhaps changing the name could be optional? The syntax
+ type <Id> is tagged separate [<Old_Name>] in <package_id>;
+is suggested. A straw poll is taken on this issue:
+ Must specify the name of the type (as opposed to some other choice) is
+ defeated by a vote of 1-6-2.
+ Support specifying the name (optionally) is defeated by a vote of 2-5-2.
+Summarizing the results of this discussion:
+1) "completion available" means "in scope of with or immediate scope of
+2) If incomplete type would be illegal in a particular context - check if
+ completion is available (as described above).
+3) Tagged incomplete allowed as actual or formal parameter; dereferencing a
+ tagged incomplete allowed as actual parameter (and as a parenthesized actual
+4) Syntax as proposed by Erhard; simple name of incomplete type = simple name
+ of completion.
+5) Type matching rules: incomplete matches incomplete if same full name of
+ completion; incomplete matches complete if complete has the full name
+ specified as the completion (taking renames into account).
+Approve intent of AI: 7-0-0
+Tucker will write the wording as soon as possible.
+From: Pascal Leroy
+Sent: Friday, March 1, 2002, 10:48 AM
+We already use the word "available" elsewhere, in the context of stream
+attributes I think. Using the same adjective for two unrelated concepts
+might be a bit confusing (I realize that the context should make it clear
+which "availability" we are discussing, but still). My thesaurus gives the
+The last two words are quite ugly. "Accessible" smells too much of
+accessibility rules. "Obtainable" and "usable" seem like the only decent
+candidates. (Unless someone has a better thesaurus.)
+From: Tucker Taft
+Sent: Friday, March 1, 2002, 11:02 AM
+I think so long as we define the term here, and use
+it all in the same section, then the fact that the
+same term appears elsewhere is probably not a major problem.
+I don't particularly like "obtainable" or "usable" in
+any case. One possibility would be to define a longer
+term such as "considered complete." For a "normal"
+incomplete type, this is anywhere within the scope of
+the completion, whereas for a type stub, it is within
+the immediate scope of the completion, or within the
+(extended) scope of the completion when also within the scope
+of a with clause for the completing package.
+From: Pascal Leroy
+Sent: Friday, March 1, 2002, 11:08 AM
+That's true, but what bothers me is that things are always more complex that
+we expect, and I wouldn't be surprised if one day we discovered the need for
+a rule where the two instances of "available" meet. Imagine a rule that
+would say "the attribute Input of a type T is only available if the
+completion of T is available." Not exactly crystal-clear if you ask me.
+From: Randy Brukardt
+Sent: Wednesday, March 6, 2002, 5:33 PM
+I *think* that we're safe here, given that the prefix of an attribute cannot be
+an incomplete type unless it is a type stub whose completion is available. So
+we're using the word in the same sense in both places. And your suggested rule
+is trivially true, given that any other use would be illegal. (But I realize
+that it is an example.)
+I'd rather avoid overloading the term, but given the options seem pretty lousy,
+I think it is OK. (Of course, if you had used "employable" for stream
+attributes, we wouldn't have this problem. :-)
Questions? Ask the ACAA Technical Agent