Effect of compiling generic unit bodies separa 87-08-20 AI-00408/11 1 | !standard 10.03 (06) 87-08-20 AI-00408/11 | !class binding interpretation 86-05-13 | !status approved by WG9/AJPO 87-07-30 | !status approved by Director, AJPO 87-07-30 | !status approved by Ada Board 87-07-30 !status approved by WG9 87-05-29 !status panel/committee-approved 87-01-19 (reviewed) !status panel/committee-approved (7+3-1-1) 86-11 (by ballot; pending editorial review) !status panel/committee-approved (6-2-1) 86-09-10 (pending letter ballot) !status work-item 86-09-10 !status failed letter ballot (0-11-2) 86-09 !status committee-approved (5-1-4) 86-05-13 (pending letter ballot) !status work-item 86-01-23 !references AI-00506, AI-00257, 83-00382, 83-00632, 83-00658, 83-00725, 83-00737, 83-00785 !topic Effect of compiling generic unit bodies separately !summary 86-09-20 An implementation is allowed to create a dependence on a generic unit body such that successfully compiling (or recompiling) the body separately makes previously compiled units obsolete if they contain an instantiation of the generic unit. A similar dependence can be created for separately compiled subunits of a generic unit. !question 86-01-23 If the body of a generic unit is recompiled, must all instantiations of the unit also be recompiled? !recommendation 86-12-03 If a unit contains a generic instantiation, an implementation can create a dependence of the given unit on the generic body; if such a dependence is created and the body is compiled successfully in a separate compilation, the compiler must recognize this dependence when deciding on the need for recompilation. (See AI-00506 if the body is not compiled separately.) A similar dependence can be created and recognized for a subunit of a generic unit body when the subunit is given in a compilation separately from the parent unit or separately from a unit containing an instance. | !discussion 87-08-20 Paragraphs 10.3(5-6) say: "... A compilation unit is potentially affected by a change in any library unit named by its context clause. A secondary unit is potentially affected by a change in the corresponding library unit. The subunits of a parent compilation unit are potentially affected by a change of the parent compilation unit. If a compilation unit is successfully recompiled, the compilation Effect of compiling generic unit bodies separa 87-08-20 AI-00408/11 2 units potentially affected by this change are obsolete and must be recompiled unless they are no longer needed. An implementation may be able to reduce the compilation costs if it can deduce that some of the potentially affected units are not actually affected by the change. The subunits of a unit can be recompiled without affecting the unit itself. Similarly, changes in a subprogram or package body do not affect other units (apart from subunits of the body) since these compilation units only have access to the subprogram or package specification. An implementation is only allowed to deviate from this rule ... as described below." Now consider the following set of files containing Ada compilation units: ----- File G_SPEC ----- generic type T is private; package G is end; ----- File G_BODY ----- package body G is X : T; end; ----- File TRY_G ----- with G; procedure PROC is package MY_G is new G(INTEGER); begin ... end; ---------------------- Suppose we compile these files in the following order: 1. Compile file G_SPEC containing generic declaration G 2. Compile file G_BODY containing generic template G 3. Compile file TRY_G containing an instantiation of G 4. Compile file G_BODY again (whether edited and changed or not is irrelevant) What is the status of unit PROC in the compilation library? Is PROC obsolete so that it must be recompiled before it can be linked and executed? Or is it perfectly okay "as is" and immediately ready to be linked and executed? As discussed below, the Standard allows PROC to be linked and executed without Effect of compiling generic unit bodies separa 87-08-20 AI-00408/11 3 being recompiled; it also allows an implementation to reject the attempt to recompile G_BODY. According to the definitions given in 10.3(5, 6), the recompilation of G_BODY does not potentially affect PROC, so recompilation of PROC is not required. In particular, 10.3(6) notes that "changes to a subprogram or package body do not affect other compilation units." This wording applies to both generic and nongeneric bodies since "package body" and "subprogram body" are syntactic terms, and these syntactic constructs are used for generic as well as nongeneric units. Paragraphs 10.3(7-8) allow certain deviations from the rules stated in 10.3(5-6) but these allowed deviations are not relevant to the example. 10.3(7) deals with pragma INLINE; AI-00200 allows additional dependences on generic unit bodies when pragma INLINE is applied to a generic unit or subprogram instantiation, but neither this paragraph nor this AI applies to the example, since pragma INLINE is not used. Paragraph 10.3(8) allows additional dependences to be created among the files belonging to a single compilation. This paragraph does not apply when generic unit bodies are processed in separate compilations, as in the example. Paragraph 10.3(9) allows an implementation to require that a generic unit body (and its subunits, if any) be placed in the same compilation as its declaration. AI-00257 says, in effect, that an implementation is free to decide when to invoke the restriction allowed by 10.3(9). In particular, an implementation might decide to accept a separate compilation containing a generic unit body only if the generic unit has never been instantiated. Thus the attempt to compile G_BODY in step 2 of the example could succeed while the attempt to recompile G_BODY in step 4 could be rejected. If the attempt to recompile the body is rejected, a user can combine the specification and body in a single compilation, which then MUST be accepted (see AI-00506 for further discussion). Of course, recompiling the generic unit specification will make obsolete any unit that contains an instantiation of the generic unit -- the net effect of forcing recompilation of the generic specification is essentially the same as if the units containing the instantiations had been made obsolete directly as a result of recompiling the generic unit body. (The net effect, however, would be worse if the generic specification were given in a library package. Recompiling the library package (together with the generic unit body) would make obsolete all units that depend on the library package, whether or not they contain any generic instantiations. Thus, some unnecessary recompilation may be required.) An implementation need not, in general, require that generic declarations and bodies (or subunits) be given in the same compilation. For example, after rejecting the recompilation of G_BODY, an implementation might accept the separate recompilation of just G_SPEC, thereby making obsolete all units that contain instantiations of G_SPEC. A user could then separately compile G_BODY, since there are no previous instantiations of unit G in the library. After recompiling G_BODY, the units containing the instantiations of G could then be compiled. So although an implementation can invoke 10.3(9) to reject certain separate recompilations of a generic unit body, it need not in practice require that generic specifications and bodies always be given in the same compilation. Effect of compiling generic unit bodies separa 87-08-20 AI-00408/11 4 In short, an implementation can require a sequence of recompilations that have the effect of making obsolete all units that contain instantiations of some generic unit. There seems to be little or no benefit to enforcing the notion that a unit containing a generic instantiation is unaffected when the corresponding generic unit body is recompiled. For all practical purposes, 10.3(9) and AI-00257 already allow an implementation to require recompilation of such instantiating units; it seems reasonable for recompilation to be required directly, rather than via the indirect ways allowed by 10.3(9) and AI-00257. Allowing an implementation to require such recompilations means separate compilation of generic unit bodies can be supported efficiently, and such support is considered highly desirable. The recommendation does not ensure that separate compilation of generic | specifications and bodies will be supported in every case, however. Consider the following example: --- File STUB procedure P is generic type T is private; procedure H; procedure H is separate; -- stub for H procedure MY_H is new H(STRING); begin null; end P; --- File H_BODY separate (P) procedure H is begin null; end H; Suppose H_BODY is compiled separately. The recommendation allows an implementation to make procedure P obsolete when H_BODY is compiled, since P contains an instantiation of H. But recompiling P makes subunit H obsolete, since P is the parent of subunit H. Thus, there is no sequence of compilations that allows P and H_BODY to be compiled separately. If an implementation supports the recommendation given in this Commentary, such a pair of units can only be compiled if they are given together in a single compilation (see AI-00506 for further discussion).