CVS difference for ais/ai-00412.txt

Differences between 1.1 and version 1.2
Log of other versions for file ais/ai-00412.txt

--- ais/ai-00412.txt	2005/02/08 02:09:18	1.1
+++ ais/ai-00412.txt	2005/02/08 02:17:39	1.2
@@ -4,7 +4,7 @@
 !status received 05-02-03
 !priority Medium
 !difficulty Medium
-!subject Subtypes of incomplete types
+!subject Subtypes of incomplete types; renamings of limited views
 
 !summary
 
@@ -12,23 +12,125 @@
 incomplete type provided they do not have any constraints or a null
 exclusion.
 
+Renaming of the limited view of a package is permitted.
+
+The view visible via a rename of a library package (or one of
+its visible subpackages) is determined by what kind of with
+clause applies at the point of reference.
+
+
 !problem
 
 The introduction of limited with clauses and the fact that use package
-clauses are not permitted with a limited view can create long names
-which cannot be abbreviated since subtype declarations are not
+clauses and renamings are not permitted with a limited view can create
+long names which cannot be abbreviated since subtype declarations are not
 permitted for an incomplete type.
 
+In writing examples for the rationale, we have found some
+of these long names tedious, and wonder whether we couldn't
+allow the declaration of subtypes, so long as no constraint is
+specified. Similarly, we wonder whether we could also permit renamings
+of limited views of packages, as this is a common alternative
+approach to "use" clauses to provide "shorthand" notations for
+entities whose full name is very long.
+
+Even if we didn't permit renaming of limited views, there is a
+question of what view of a package is visible via a renaming
+declared in a place that has a full view, but referenced in
+a place that has only a limited view of a package.
+
 !proposal
 
-(See summary.)
+To answer the last issue first -- if referenced from within the scope
+of a limited with for a package, any renaming of that package that
+might occur in some other compilation unit provides the
+same limited view. Similarly, if the package has nested packages, then
+renames of those also provide limited views when referenced from inside
+the scope of the limited with.
+
+We propose to allow declarations of constraint-less subtypes of incomplete
+types, and renamings of limited views. These have slightly different
+rules, so we will describe them separately.
+
+For an incomplete type other than one implicitly declared in a limited view of
+a package, a named subtype denotes the full view of the type where
+the full view is visible. For an incomplete type from a limited view
+of a package, a named subtype denotes the full view when within the
+scope of a non-limited with clause for the enclosing library unit.
+Otherwise it denotes the incomplete view. This is intended to mirror the
+rules for access-to-incomplete types.
+
+For a renaming of a limited view, the renaming may only be used within
+the scope of a limited or non-limited with clause for the enclosing
+library unit. If neither kind of with clause for the library
+unit containing the viewed package applies to a given place, no
+reference to the renaming is permitted. If within the scope
+of a with clause, then if it is limited, a limited view is provided,
+if the with clause is non-limited, then a full view is provided.
+This ensures that only one view of a given package is visible
+at a given point.
+
+These rules are intended to ensure that there is never the need
+to implicitly produce a full view of a package as a side effect
+of referencing a renaming of a limited view or a subtype of an
+incomplete type, except within the scope of a non-limited with
+clause for the package. Equivalently, after processing the context
+clause, for any given library package, no further views will be
+needed.
 
 !wording
 
-Add after 3.10.1(6/2) (might as well reuse 7/2 which is now empty)
+Add after 3.10.1(2.5/2):
 
-*   as the subtype_mark in the subtype_indication of a subtype_declaration;
-    the subtype indication shall not have a null_exclusion or a constraint;
+ Similarly, if a subtype_mark denotes a subtype_declaration defining
+ a subtype of an incomplete view T, the subtype_mark denotes an
+ incomplete view except under the same two circumstances given above,
+ in which case it denotes the full view of T.
+
+Add after 3.10.1(6/2) (might as well reuse 7/2 which is now empty):
+
+ *  as the subtype_mark in the subtype_indication of a subtype_declaration;
+    the subtype_indication shall not have a null_exclusion or a constraint;
+
+
+Revise 8.3(20) as follows:
+
+ *
+    The declaration of a library unit (including a
+    library_unit_renaming_declaration) is hidden from all visibility at
+    places outside its declarative region that are not within the scope
+    of a nonlimited_with_clause that mentions it. The {declaration} of
+    the limited view of a library package is hidden from all visibility
+    at places that are not within the scope of a limited_with_clause
+    that mentions it; in addition, the {declaration of the} limited view
+    is hidden from all visibility within the declarative region of the
+    package, as well as within the scope of any nonlimited_with_clause
+    that mentions it. {Where the declaration of the limited view of a
+    package is visible, all views of the package are limited, including
+    those provided by a package renaming.}
+
+ *
+    Redundant:[For each declaration or renaming of a generic unit as a
+    child of some parent generic package, there is a corresponding
+    declaration nested immediately within each instance of the parent.]
+    Such a nested declaration is hidden from all visibility except at
+    places that are within the scope of a with_clause that mentions the
+    child.
+
+Drop the restriction of 8.5.3(3/2) that requires the
+view be nonlimited. Instead, add the following:
+
+  If the package_name denotes a limited view of a package, then the
+  package_renaming_declaration shall not be referenced outside its
+  immediate scope, except within the scope of a with_clause
+  that mentions the package or (for a nested package) the
+  nearest enclosing library package.
+
+Add after 8.5.3(4):
+
+  Redundant:[At places where the declaration of the limited view of the renamed
+  package is visible, a name that denotes the package_renaming_declaration
+  denotes a limited view of the package (see 10.1.1).]
 
 
 !discussion
@@ -68,7 +170,7 @@
 The use of meaningful package names and variable names is good practice
 but when put together they can be overwhelming. The renaming enables an
 abbreviation to be used locally but ensures that the full name is still
-visible to the human reader.  In the case of types, renaming is not
+visible to the human reader. In the case of types, renaming is not
 appropriate but a subtype serves an equivalent purpose thus
 
    subtype T is Long_Package_Name.Long_Type_Name;
@@ -88,9 +190,240 @@
 Clearly however, we know little about the type (except that it might be
 tagged) and so constraints and not null are not permitted.
 
-The only other things made visible by a limited with clause are the names
-of the package itself and any nested packages. Renaming is already
-permitted for them.
+The only other things made visible by a limited with clause are the
+names of the package itself and any nested packages. We are also
+proposing to allow renaming of such packages.
+
+Because subtype declarations and package renamings can be used to
+"re-export" items made visible in a unit via limited with clauses, we
+need to be concerned about what are the properties of these re-exported
+views.
+
+One concern is about "ripple" effects, by which we mean that the
+addition, removal, or change of a with clause on some "distant" member
+of the semantic closure of a unit might affect the legality of the given
+unit. In particular, we are worried what happens when we change a
+"with" clause to a "limited with" clause, or vice-versa.
+
+In the past, we have been concerned primarily about ripple effects
+relating to a rule that causes the presence or absence of a particular
+unit in the semantic closure to affect the legality of otherwise
+unrelated constructs. For example, in Ada 83, the 'Address attribute
+was only legal if package System was somewhere within the semantic
+closure. This notion was dropped in Ada 95, as it is surprising during
+maintenance, and it makes incremental compilation that much harder.
+
+In the case of the "limited with," we tried to avoid having ripple
+effects that determined whether the dereference of an
+access-to-incomplete type was itself incomplete based on whether there
+was a non-limited with clause on the package defining the full type
+somewhere in the closure. We ultimately decided the with clause had to
+be on the unit itself. But we also allowed incomplete to match complete
+in more circumstances.
+
+Nevertheless, we are still left with a semi-ripple effect, in that if
+the place where the access type is declared changed its with clause from
+a non-limited to a limited with clause, the dereference of an access
+value of the type shifts from being non-incomplete to incomplete. This
+is a "semi" ripple effect in that there must be an unbroken chain of
+references crossing only direct "with" clause dependences back to the
+unit whose with clause is changed. This does not seem as bad. This is
+more like there being two separate packages, P1 and P2, both defining a
+type T, one private and one non-private, and a third package defining an
+access-to-T type. If the third package changes its with clause to "with
+and use" P2 rather than P1, then the properties of the designated type
+of the access-to-T changes, and if we make use of values of that type,
+they change from being access-to-non-private-T to access-to-private-T.
+That of course is not at all surprising.
+
+Effectively we should realize that changing a "with" clause
+to a "limited with" is somewhat like change "with P1" to "with P2."
+We are seeing a significantly different set of types and subpackages.
+If we reexport entities whose properties derive from declarations
+within P1 and P2, or equivalently, within the full or limited
+view of a package, then the change in the with clause will
+certainly be visible to those who import those entities.
+
+We have tried to isolate this somewhat, by saying that if the
+"importing" unit itself has a "with" or "limited with" clause
+on the package, then that determines its view of a renaming,
+a subtype-of-T, or an access-to-T. If it has neither kind
+of with clause, then for subtype-of-T and access-to-T, the
+incomplete/access-to-incomplete view is provided. For renaming,
+we make neither view available.
+
+For renaming and subtype-of-T, we considered providing an
+"implicit" non-limited "with" if needed, but it was pointed out
+that there are implementations that rely on the context clause
+to determine order of compilation, and having such implicit
+dependences on the full view of a package would seriously
+undermine that approach. This alternative is considered in
+more depth in the following.
+
+A REJECTED ALTERNATIVE
+
+A possible alternative is to say that you always get the full
+view, *unless* you are in the scope of a limited with.
+This would probably have friendlier behavior during maintenance, and
+during transition to Ada 2005.
+
+Let's take a specific scenario. We have two packages
+in Ada 95, P_Pkg and Q_Pkg, which declare T and U,
+respectively. We would really like to have P_Pkg
+have operations on U, and Q_Pkg have operations on T,
+but we get into a cycle, so we play the "class-wide"
+type trick, as follows:
+
+    package Q_Root_Pkg is
+       type Q_U_Root is tagged ...
+    end Q_Root_Pkg;
+
+    with Q_Root_Pkg; use Q_Root_Pkg;
+    package P_Pkg is
+       type T is tagged ...
+       procedure Cyclic(X : Q_U_Root'Class);
+         -- I really wanted to take Q_Pkg.U but
+         -- I am using the old Ada 95 class-wide
+         -- trick to avoid the circularity.
+         -- In the body of Cyclic I'll convert X to Q_Pkg.U.
+    end P_Pkg;
+
+    with Q_Root_Pkg; use Q_Root_Pkg;
+    with P_Pkg;
+    package Q_Pkg is
+       package P_Ren renames P_Pkg; -- declare a shorthand
+       subtype P_T is P_Ren.T;      -- declare a shorthand
+       type U is new Q_U_Root with ... -- for the class-wide trick
+       procedure Fun(Y : P_T);
+    end Q_Pkg;
+
+Now let's suppose that we have lots of existing code
+that depends on Q_Pkg, and makes use of some of the
+shorthands it declares:
+
+    with Q_Pkg; use Q_Pkg;
+    procedure Some_Random_Procedure is
+       A : P_Ren.T; -- use shorthand
+       B : P_T;     -- use shorthand
+    begin
+       Fun(A); Fun(B);
+    end;
+
+Now along comes Ada 2005, and we realize we can change the "with" of P_Pkg
+to a "limited with" of P_Pkg, and then
+add a "with" of Q_Pkg on P_Pkg, and change the
+Cyclic procedure to take a Q_Pkg.U directly, rather than
+playing the class-wide type game.
+
+We also have these shorthands declared
+in Q_Pkg. We can erase them, but then who
+knows how much code is using them. But with this
+proposal, we allow shorthands to be
+used even in the presence of limited with,
+so I'm saved.
+
+Hence, we can leave the shorthands there, change
+the "with" of P_Pkg to a "limited with" of P_Pkg,
+and fix Cyclic to produce:
+
+    with Q_Pkg; use Q_Pkg;
+    package P_Pkg is
+       type T is tagged ...
+       procedure Cyclic(X : U);
+         -- In Ada 2005 I can say what I mean!
+    end P_Pkg;
+
+    limited with P_Pkg;
+    package Q_Pkg is
+       package P_Ren renames P_Pkg; -- declare a shorthand
+       subtype P_T is P_Ren.T;      -- declare a shorthand
+       type U is tagged ...
+       procedure Fun(Y : P_T);
+    end Q_Pkg;
+
+Unfortunately, all the compilation units that were using
+the shorthands are now in trouble, depending on what are the
+rules relating to the re-export of limited/incomplete views.
+
+There are various choices, and conceivably one could
+make different choices for package renaming and subtype
+declarations (and deref of access-to-incomplete):
+   1) In the absence of a "with" or "limited with" clause:
+        a) you see the same view as was present at the place
+           where the shorthand was declared;
+        b) you see the full view
+   2) In the presence of a "with" clause:
+        a) you see the same view as at the place where the shorthand
+           was declared
+        b) you see the full view
+   3) In the presence of a "limited with" clause:
+        a) you see the same view as at the place where the shorthand
+           was declared
+        b) you see the limited/incomplete view
+
+We haven't talked much about (1), but for package renaming, we are
+proposing 2(b) and 3(b) -- the "local" with clause wins.
+
+For subtypes, we agree that for 3, we want (a), that is the subtype
+doesn't "become incomplete". We are proposing that we allow "shorthand"
+subtypes of incomplete types, but we haven't really concluded whether we
+want 2(a) or 2(b) for them, that is do we want them to "become full"
+when viewed from a place that has a full view on the package.
+
+For deref of access-to-incomplete, we seem to have 2(b) and 3(b). When
+neither a "with" or a "limited with" is in scope, we seem to treat it as
+an incomplete view, but allow it to match the full view.
+
+If you look at it from the transition and maintenance point of view, it
+would seem ideal if changing a "with" to a "limited with" really *only*
+affected the compilation units in the scope of the limited with clause.
+Any other compilation units are unaffected. This would say that our
+rule for deref of access-to-incomplete is not quite right. We shouldn't
+require the location of the deref (e.g. procedure P3 in example given
+near the top) to add a "with" clause just because the place where the
+access type was declared (package P2) changed a "with" to a "limited
+with." This would also argue that you see the full view via a shorthand,
+unless you are in the scope of a limited with.
+
+An implication of this approach is that you end up with an implicit
+semantic dependence on the full view if you dereference an
+access-to-incomplete or use a subtype-of-incomplete name outside the
+scope of a limited with, and you use the deref or the subtype name in a
+way that would be illegal if it were incomplete (e.g. using a deref as a
+prefix, or using the subtype to declare an object).
+
+Similarly, if you use a package rename in a context outside of the scope
+of a limited with for the renamed package (or its enclosing library
+unit), other than in another renaming, you get the full view (and hence
+an implicit semantic dependence on the full view).
+
+This approach relates to the choice we made in Ada 95 to create an
+implicit semantic dependence on package System when the 'Address
+attribute is used. Essentially, we are saying that the clients of a
+package that has only a limited view on a package may end up with an
+implicit semantic dependence on the full view of the package.
+
+Equivalently, if you need to break circularity, then you need to change
+a with clause to a limited with, or *add* a limited with, on one or more
+units that are part of the circularity. But you never have to add a
+"with" clause on units *outside* the circularity.
+
+BOTTOM LINE:
+
+We propose to allow subtype-of-incomplete and renaming limited views.
+We also want to minimize ripple effects. Finally, we want to preserve
+the principle that the context clause determines the semantic
+dependences (ignoring language-defined implicit dependences on certain
+standard packages).
+
+The net effect is that when you change a with clause of some unit Q from
+"with P" to "limited with P," some of the clients of Q may need to add
+their own "with P" to remain compilable. This is because Q may now be
+exporting access-to-incomplete, subtype-of-incomplete, and
+renaming-of-limited, and a "with P" may be needed in the client to turn
+these back into access-to-complete, subtype-of-complete, and
+renaming-of-full-view. It is the intent that no other changes
+to clients would be necessary to survive this shift in Q.
 
 !example
 

Questions? Ask the ACAA Technical Agent