!standard 10.1.3 (8) 05-06-08 AI95-00243/03 !class binding interpretation 00-10-04 !status Amendment 200Y 02-10-23 !status WG9 Approved 02-12-13 !status ARG Approved 10-0-0 02-10-12 !status work item 00-10-04 !status received 00-10-04 !qualifier Omission !priority High !difficulty Medium !subject Is a subunit of a subunit of L also a subunit of L? !summary A subunit of a subunit of some unit is considered to be a subunit of that unit. !question Consider the following compilation units: package Parent is procedure Whatever; end Parent; private package Parent.P_Child is procedure Do_It; end Parent.P_Child; package body Parent is package Sep is procedure Proc; end Sep; package body Sep is separate; procedure Whatever is begin null; end Whatever; end Parent; separate (Parent) package body Sep is procedure Proc is separate; end Sep; with Parent.P_Child; separate (Parent.Sep) procedure Proc is begin Parent.P_Child.Do_It; end Proc; Is it legal for the body of Parent.Sep.Proc, a subunit of a subunit of package Parent, to with Parent.P_Child, a private child of Parent? (Yes.) 10.1.2(8) says: If a with_clause of a given compilation_unit mentions a private child of some library unit, then the given compilation_unit shall be either the declaration of a private descendant of that library unit or the body or subunit of a (public or private) descendant of that library unit. Technically, Parent.Sep.Proc is not a subunit of a descendant of Parent. It is a subunit of a subunit of Parent. A strict reading of the RM would make the body of Parent.Sep.Proc illegal. However, it seems that the intent of 10.1.2(8) is to refer to all subunits occurring within the declarative region of a library unit. Is this correct? (Yes.) !recommendation (See summary.) !wording (See corrigendum.) !discussion There is a language design principle that any body can be made into a subunit by replacing it in the original unit by an appropriate stub and by adding a separate declaration for the parent unit. There should not be a case where something is legal on B, and on a subunit of B, but not on a subunit of a subunit of B. However, the language of the standard can be read to not allow with_clauses of private units on subunits of subunits of a unit on which the clause would be allowed. Similar wording in 10.2(9) has similar problems. Therefore a general solution of defining "a subunit of unit U" to include any subunits of subunits of U has been adopted. !corrigendum 10.1.3(8) @drepl The @i of a subunit is the body of the program unit denoted by its @fa. The term @i is used to refer to a @fa and also to the @fa of a @fa. @dby The @i of a subunit is the body of the program unit denoted by its @fa. The term @i is used to refer to a @fa and also to the @fa of a @fa. The @i include any subunit that names that program unit as its parent, as well as any subunit that names such a subunit as its parent (recursively). !ACATS test !appendix From: Vincent Celier Sent: Wednesday, September 13, 2000 8:11 PM !topic Is a subunit of a subunit of L also a subunit of L? !reference RM95-10.1.2(8) !from Vincent Celier 00-09-13 !discussion Consider the following compilation units: package Parent is procedure Whatever; end Parent; private package Parent.P_Child is procedure Do_It; end Parent.P_Child; package body Parent is package Sep is procedure Proc; end Sep; package Sep is separate; procedure Whatever is begin null; end Whatever; end Parent; separate (Parent) package body Sep is procedure Proc is separate; end Sep; with Parent.P_Child; separate (Parent.Sep) procedure Proc is begin Parent.P_Child.Do_It; end Proc; Is it legal for the body of Parent.Sep.Proc, a subunit of a subunit of package Parent, to with Parent.P_Child, a private child of Parent? RM 10.1.2(8) says: If a with_clause of a given compilation_unit mentions a private child of some library unit, then the given compilation_unit shall be either the declaration of a private descendant of that library unit or the body or subunit of a (public or private) descendant of that library unit. Technically, Parent.Sep.Proc is not a subunit of a descendant of Parent. It is a subunit of a subunit of Parent. A strict reading of the RM would make the body of Parent.Sep.Proc illegal. However, it seems clear that the intent of 10.1.2(8) is to refer to all subunits occuring within the declarative region of a library unit. However, different compilers could have different interpretations. **************************************************************** From: Tucker Taft Sent: Friday, September 22, 2000 10:02 PM > Is a subunit of a subunit of L also a subunit of L? Yes. > Is it legal for the body of Parent.Sep.Proc, a subunit of a subunit > of package Parent, to with Parent.P_Child, a private child of Parent? Yes. > Technically, Parent.Sep.Proc is not a subunit of a descendant of Parent. > It is a subunit of a subunit of Parent. No, there are several places in the RM where subunits of subunits of L are considered subunits of L also. Interestingly, there is no explicit definition of "subunit of L" that I could find. However, here are a few paragraphs that rely on its (implicit) definition being transitive: 10.1.2(5) 10.2(9) 10.1.4(2) E.3(4) > A strict reading of the RM would make the body of Parent.Sep.Proc illegal. > However, it seems clear that the intent of 10.1.2(8) is to refer to all > subunits occuring within the declarative region of a library unit. I don't see any need to change the RM wording. **************************************************************** From: Robert Dewar Sent: Friday, September 22, 2000 10:07 PM I am realy puzzled by Tuck's comment here, he announces ex cathedra that a subunit of a subunit of L is also a subunit of L, which to me is not at all obvious, since I tend to interpret "of" syntactically. He then notes that nowhere in the RM is subunit of L defined, and hence nowhere in the RM is anything that would prove the above statement. And finally he says <> after noting that a strict reading of the RM yields clearly unintended results. All very puzzling, I was following Tuck up to the point where he said he saw no need to change the RM wording and at that point he lost be completely. **************************************************************** From: Randy Brukardt Sent: Friday, September 22, 2000 10:20 PM I have to agree with Robert. Perhaps there was some intent that a subunit of X includes a subunit of a subunit of X, but that intent certainly doesn't seem derivable from the standard. Announcing that the standard is wrong and we don't need to fix it doesn't make much sense to me. It seems clear that if there is no definition of subunit of X, and it is supposed to include subunits of subunits of X, the solution is to add wording to say that somewhere. This certainly seems to be a binding interpretation, not a confirmation. (There is at least as much reason to believe the standard meant the other interpretation). **************************************************************** From: Tucker Taft Sent: Sunday, September 24, 2000 7:48 PM I identified 3 places in the standard where, implicitly, "subunits of L" includes subunits of subunits of L, so clearly the opposite interpretation wouldbe inconsistent. I can see some value of adding a definition of "subunits of L" explicitly. What I meant was that there was no need to change the wording of the paragraph identified in the comment. If we do want to change the wording (though I claim that it is possible to infer the meaning of "subunits of L" from various usages, including the one in question), then clearly we would want to do it in the clause devoted to subunits. **************************************************************** From: Robert Dewar Sent: Saturday, September 23, 2000 7:03 AM <> Indeed GNAT implemented the other interpretation until we got a bug report which made us think that probably the intention *was* reasonably that a subunit of a subunit of L is a subunit of L, so we changed th implementation to this modified (but not really RM justified) viewpoint. **************************************************************** From: Christoph Grein Sent: Monday, September 25, 2000 3:06 AM Robert Dewar wrote: > Indeed GNAT implemented the other interpretaiton until we got a bug report > which made us think that probably the intention *was* reasonably that > a subunit of a subunit of L is a subunit of L, so we changed th > implementation to this modified (but not really RM justified) viewpoint. May I just add a comment from a poor (pure) Ada user's point of view. A subunit behaves in all respects (except wrt with clauses) as though it were directly defined inside its parent unit. Thus if a with clause is allowed in the parent unit, and later I decide to take part of it into a separate (and thereby can make the import with clause more local), I would find it very surprising (to say the least) if suddenly this would be illegal because a subunit of a subunit of L is NOT a subunit of L. This is, I think, why you received the bug report (and accordingly changed Gnat). But I know, law and common sense seldom go together... **************************************************************** From: Randy Brukardt Sent: Wednesday, October 04, 2000 6:05 PM I'm working on writing the AI for this discussion, and I've decided to analyze Tucker's claim: > I identified 3 places in the standard where, implicitly, "subunits of L" > includes subunits of subunits of L, so clearly the opposite interpretation > would be inconsistent. Here is a paragraph-by-paragraph analysis of this claim. I've looked for each use of "subunit" where transitivity might be needed: 8.4(6): "...the scope is the entire body and any subunits (including multiply nested subunits)." -- Transitivity is given explicitly here. This suggests that where it is not mentioned, it is not intended. 10.1.2(5): The scope of a with_clause that appears on a library_unit_declaration or library_unit_renaming_declaration consists of the entire declarative region of the declaration, which includes all children and subunits. The scope of a with_clause that appears on a body consists of the body, which includes all subunits. -- "all subunits" is very inclusive. Nowhere is that restricted to "all subunits of some unit". Certainly the wording is already transitive. In the first case, the "entire declarative region" accomplishes that, but in the second case, it appears to include all subunits in the world. Nothing discussed here would have any effect on this case, so it provides no support for Tuck's position (or any other position, for that matter). 10.1.2(8): If a with_clause of a given compilation_unit mentions a private child of some library unit, then the given compilation_unit shall be either the declaration of a private descendant of that library unit or the body or subunit of a (public or private) descendant of that library unit. -- This is paragraph under discussion. There is no evidence (other than consistency with the same program without the subunits) that the intent was that this should be transitive. 10.1.4(2): "... Each included subunit occurs in place of the corresponding stub...." -- Again, the terminology "subunit of some unit" does not appear here. It seems that the natural interpretation of this is transitive, without appealing to any intent at all. That is, for every stub, replace by its subunit. Again, no support for Tuck's position. 10.2(6): "If a compilation unit with stubs is needed, then so are any corresponding subunits." -- Tucker did not mention this one, but it clearly is the same as 10.1.4(2). 10.2(9): The order of elaboration of library units is determined primarily by the elaboration dependences. There is an elaboration dependence of a given library_item upon another if the given library_item or any of its subunits depends semantically on the other library_item. In addition, if a given library_item or any of its subunits has a pragma Elaborate or Elaborate_All that mentions another library unit, then there is an elaboration dependence of the given library_item upon the body of the other library unit, and, for Elaborate_All only, upon each library_item needed by the declaration of the other library unit. -- This one does use the "subunit of some unit" wording (well, in reverse). And it ought to be transitive. Point for Tuck's position. 10.2.1(11/1): "... The declaration and body of a preelaborated library unit, and all subunits that are elaborated as part of elaborating the library unit, shall be preelaborable. ..." -- This wording is naturally transitive, and does not lean on any interpretation of "subunit of some unit". E.3(4): "...that contains the body (but not any subunits) of the program unit." -- Transitivity is necessary. However, the wording is all-exclusive; it really doesn't need to exclude *just* the subunits of the program unit; excluding *all* subunits anywhere works just as well. Not strong support. These are all of the paragraphs that mention "subunits" in relation to another unit. So, of the eight paragraphs that seem to require transitivity, only two really depend on it; for the rest, the existing wording seems to provide it without modification or appeals to intent. Thus, it appears clear that we need to repair the two that do need "magic transitivity" to make sense. Tucker prefers defining "subunit of L" recursively, and that does seem to be the best solution. It doesn't seem to have any negative effects based on my research. **************************************************************** From: Robert A Duff Sent: Friday, October 06, 2000 8:29 AM > 8.4(6): "...the scope is the entire body and any subunits (including > multiply nested subunits)." > -- Transitivity is given explicitly here. This suggests that where it is > not mentioned, it is not intended. I read this to mean just the opposite. Sort of like "...all subsets of S (including S itself)", or "all integers (including the negative ones)". That is, the parenthetical "including" implies that we're just giving you a friendly reminder of some case you might have forgotten. > 10.1.2(5): > The scope of a with_clause that appears on a library_unit_declaration or > library_unit_renaming_declaration consists of the entire declarative > region > of the declaration, which includes all children and subunits. The scope > of > a with_clause that appears on a body consists of the body, which > includes > all subunits. > -- "all subunits" is very inclusive. Nowhere is that restricted to "all > subunits of some unit". Certainly the wording is already transitive. In the > first case, the "entire declarative region" accomplishes that, but in the > second case, it appears to include all subunits in the world. Sounds like a rather unfriendly reading. *Of course* we mean all subunits of that body. And we want that to include sub-sub-ever-so-subunits. > Thus, it appears clear that we need to repair the two that do need "magic > transitivity" to make sense. Tucker prefers defining "subunit of L" > recursively, and that does seem to be the best solution. It doesn't seem to > have any negative effects based on my research. Sounds good. Surely we all agree on the answer, if not on the wording? ****************************************************************