From ploedere@grimm.informatik.uni-stuttgart.de Tue Jul 11 19:09:37 1995 Return-Path: Received: from inmet.camb.inmet.com by dsd.camb.inmet.com (4.1/SMI-4.1) id AA09303; Tue, 11 Jul 95 19:09:37 EDT Received: from sw-eng.falls-church.va.us (ns1.sw-eng.falls-church.va.us) by inmet.camb.inmet.com (4.1/SMI-4.1) id AA02146; Tue, 11 Jul 95 19:09:26 EDT Received: from ifi.informatik.uni-stuttgart.de by sw-eng.falls-church.va.us (8.6.11/) id XAA24668; Tue, 11 Jul 1995 23:10:23 GMT Received: from grimm.informatik.uni-stuttgart.de by ifi.informatik.uni-stuttgart.de with SMTP; Wed, 12 Jul 95 01:08:26 +0200 Received: by grimm.informatik.uni-stuttgart.de with SMTP; Wed, 12 Jul 1995 01:08:47 +0200 Received: by hesse.progsprach.informatik (5.x/SMI-SVR4) id AA09653; Wed, 12 Jul 1995 01:08:29 +0200 Date: Wed, 12 Jul 1995 01:08:29 +0200 From: Ploedereder@informatik.uni-stuttgart.de (Erhard Ploedereder) Message-Id: <9507112308.AA09653@hesse.progsprach.informatik> To: ada-comment@sw-eng.falls-church.va.us Subject: DRAFT of AI95-00040 !topic DRAFT of AI95-00040; Program unit pragmas in generic units <> !discussion !standard 08.03 (16) 95-06-25 AI95-00041/00 !standard 08.03 (18) !standard 10.01.05 (02) !standard 10.01.05 (07) !standard 12.03 (13) !standard 12.03 (14) !class binding interpretation 95-06-25 !status received 95-06-25 !subject Program unit pragmas in generic units !summary 95-06-25 Program unit pragmas within a generic unit and applying to the generic unit itself do not apply to instances of the generic unit, unless a specific semantic rule of the pragma specifies the contrary. If the user wants such a pragma to apply to an instance, then it must be repeated explicitly for the instance. !question 95-06-25 Do program unit pragmas and in particular library unit pragmas within a generic unit and referring to the generic unit apply to all instances of the generic unit ? Consider: generic generic ... ... package P is package Q is pragma Pure(P); pragma Pure; ... ... end P; end Q; package PI is new P(...); package QI is new Q(...); Does the pragma Pure apply to the respective instances PI and QI ? Since pragma Pure is a library unit pragma, are instantiations of P and Q illegal, if the resulting instances are not library units ? !recommendation 95-06-25 Program unit pragmas within a generic unit and applying to the generic unit itself do not apply to instances of the generic unit, unless a specific semantic rule of the pragma specifies the contrary. A sentence to this effect should be appended to 10.1.5(2). If the user wants such a pragma to apply to an instance, then it must be repeated explicitly for the instance. A respective note to the user should be added to 10.1.5. ARM 12.4(14) should read ([..] indicates added text): "...except in the case of a name that denotes the generic_declaration or some declaration in within the generic unit; [in the first case, the corresponding name in the instance then also denotes the current instance (see 8.6), in the second case] the corresponding name in the instance then denotes the corresponding copy of the denoted declaration. ..." The anomaly of pragma INLINE applying to all instances is based on an explicit semantic rule of the pragma. (It may be regarded by implementers as an example of how implementation-defined pragmas for generic units may well be explicitly specified to apply to all instances.) !wording 95-06-25 !discussion 95-06-25 First, the relevant ARM paragraphs: (The elisions ".." omit text irrelevant for the question at hand.) 12.3(13) states: "The instance is a copy of the text of the template". 12.3(14) continues: "The interpretation of each construct within a generic declaration .. is determined using the overloading rules when that generic declaration .. is compiled. In an instance, the interpretation of each (copied) construct is the same, except in the case of a name that denotes the generic_declaration ..; the corresponding name in the instance then denotes the corresponding copy of the denoted declaration." 8.3(16,18) reaffirmes this "current instance rule": "Each occurrence of a usage name denotes the declaration determined by its interpretation. It also denotes the view declared by its denoted declaration, except in the following cases: ... If a usage name appears within the declarative part of a generic_declaration .. and it denotes that same generic_declaration then it denotes the current instance of the generic unit (rather than the generic unit itself). 10.1.5(2) states: "A name given as the argument of a program unit pragma ... shall resolve to denote the declaration of the immediately enclosing program unit (if any); the pragma applies to the denoted program unit. If there are no names given as arguments, the pragma applies to the immediately enclosing program unit." Finally, 10.1.5(7): "The name, if any, in a library unit pragma shall denote the declaration of a library unit." From 8.3(16) we conclude that a usage name denotes both the declaration AND the view declared by the denoted declaration. The "current instance rule" applies only to the view, not to the denoted declaration, which is always the declaration of the generic unit. Interpreting 10.1.5(7) literally in the context of 8.3(16), we can conclude that its restriction does not apply to the instance PI, since the denoted generic declaration is a library unit. (Note that 10.1.5(7) refers to the declaration, not to the declared program unit.) An instantiation at non-library level is therefore legal. However, 10.1.5(2) contradicts, at least in spirit, this interpretation, since it states "The pragma then applies to the denoted program unit" (which is the entity declared by the denoted declaration and hence subject to the "current instance rule"). (So, while the pragma would not prevent non-library instantiation, its effects would still apply to the current instance. This would create interesting questions, for example, for the semantics of a pragma Preelaborate applying to a locally declared instance.) Also, 12.3(14) confuses the issue further, as it states that the usage name denotes the copy of the denoted declaration (rather than the denoted declaration), thus leaning towards a uniform current instance rule. The situation is different for the instance QI (containing the pragma without arguments). Here, the current instance rule or denotation of a declaration by a name is irrelevant, since there is no name involved. We can only resort to 12.3(13,14), which regards the instance as a copy of the text of the template, where the interpretation of each (copied) construct is the same as in the template, while none of the exceptions stated in 12.3(14) applies to our case. Here, one might conclude that the pragma applies only to the generic unit, since "the interpretation stays the same" in an instance. On the other hand, we can read 10.1.5(2): "If there are no names given as arguments, the pragma applies to the immediately enclosing program unit.", combine this with the notion that the instance is a copy of the template, and conclude that the (copied) pragma applies to this copied enclosing program unit, i.e. the instance. We note in passing that the wording of 12.4(14) refers, for our case, to "a copy of the generic_declaration". This concept is not used anywhere else. This copy cannot be the "instance", which is a package, not a generic package, and hence could not be declared by that copy. What semantics are associated with this copy ? Is it an implicit declaration ? Does it introduce a name ? One can surmise that an unfortunate abbreviation has taken place here that clouds the issue at hand by stating that the usage name not only denotes the generic_declaration and also the current instance (ARM 8.3(16,18)), but also this (rather undefined) copy of the generic_declaration. 12.4(14) should be expanded to read "...except in the case of a name that denotes the generic_declaration or some declaration in within the generic unit; [in the first case, the corresponding name in the instance then also denotes the current instance (see 8.6), in the second case] the corresponding name in the instance then denotes the corresponding copy of the denoted declaration. ..." The insertion merely reiterates 8.3(18), separating this case from the (correct) semantics of other usage names denoting nested declarations within the generic unit and instance, respectively. This short exegesis of the ARM shows that there is no clear answer found in the ARM to the questions at hand. One therefore needs to examine the consequences of possible alternative answers. In any case, the effect of the pragma without argument should be the same as the pragma with argument, as the former is surely intended as a shorthand for the latter. The affected predefined library unit pragmas are: All_Calls_Remote, Elaborate_Body, Preelaborate, Pure, Remote_Call_Interface, Remote_Types, Shared_Passive. The pragmas Elaborate and Elaborate_All are irrelevant, since they cannot refer to the unit in which they occur. Additional program unit pragmas are Convention, Export, Import, and Inline, of which only Inline is defined for generic units. Program unit pragmas applied to generic subprograms are not affected by the current instance rule, since par force they occur outside the generic unit; ARM 10.1.5(4). Hence, neither 12.3(13,14) nor 8.6(16,18) apply. Consequently, such pragmas can not be interpreted as applying to instances of such subprograms on the basis on instantiation and name interpretation rules. Note, however, that pragma INLINE (historically) subscribes to the rule that it applies to all instances, when given for a generic subprogram. Its application to all instances relies exclusively on explicitly stated semantics of the pragma; ARM 6.3.2(5). This creates a quite different situation from applicability of pragmas to instances due to general name interpretation rules. Alternative 1: "pragmas in generic units apply to instances": Arguably, it would contribute to conceptual unity, if the "current instance rule" were uniformly applied to all usage names of a generic unit. This would avoid the very fine distinction between the declaration denoted by a usage name and the view declared by the denoted declaration. It would also avoid the difference in pragma effects compared to the INLINE pragma, even though these effects are achieved through two completely independent language rules (name interpretation vs. explicitly specified pragma semantics). We can further surmise from the nature of the predefined program unit pragmas that (most) instances of generic units to which they apply share the same characteristics. Using the current instance rule for pragmas, the user need not repeatedly specify the pragma for each instance. However, such a rule also implies that generic units containing library unit pragmas cannot be instantiated other than as library units. (If local instantiations were legal, at least the semantics of pragma Preelaborate requiring elaboration of the unit prior to all non-preelaborated library units of the partition would be impossible to obey for such instances). The rule would further imply that instantiations violating the pragma are always illegal. Perhaps the most aggravating consequence is the following: with user_defined_function; generic ... package P is pragma Preelaborate; X: integer := user_defined_function; ... end P; The generic unit is legal, since its elaboration does not call the imported function. (The purpose of the pragma is merely to ensure that the elaboration of the generic body occurs prior to the elaboration of all non-preelaborated library units; i.e., to avoid the need for elaboration checks upon instantiations). Yet, all its instances would be illegal, since they are not preelaborable ! The semantics of pragma Preelaborate can been regarded as an expression of intent that the pragma not be automatically applicable to all instances. Otherwise the pragma should have enforced its restrictions on the nested declarations within the generic package to detect the above problem prior to any instantiation. Note that in this as in all other examples of the AI the user does not have the option of placing the pragma outside the generic package and thereby escape a "current instance rule" selectively, since such placement is not allowed for pragmas on generic packages; ARM 10.1.5(4). The latter rule is well justified by the generally underlying one-pass model of Ada compilation. Another example with serious ramifications is: generic type T is private; package Q is pragma Pure(Q); type TN is new T; ... end Q; The intention of pragma Pure in this package is to indicate that this generic unit could (but need not) be instantiated to yield a pure package. E.g.: type Acc is access TT; package Q_Acc is new Q(Acc); -- not a pure package package Q_Int is new Q(Integer); Pragma Pure(Q_Int); With the current instance rule applied to pragmas, the package Q_Acc is illegal. This puts the writer of reusable generic packages that satisfy the necessary conditions for pure instances into a serious dilemma: If the pragma Pure is inserted, the reusability is curtailed to pure instances only. If the pragma Pure is not inserted, reusability is curtailed, because instances can then not be pure, since the purity rules prohibit the necessary dependency on the generic unit. Equivalent problems arise with other categorization pragmas. Thus, there are some highly undesirable consequences on the user in applying the current instance rule to these language-defined pragmas. Finally, to create uniformity for pragmas applicable to generic packages and generic subprograms, an additional general rule would have to be added to the language that extends applicability of pragmas for generic subprograms to their instances. Alternative 2: "pragmas in generic units do not apply to their instances" Here, the user disadvantages cited above do not exist, since pragmatic information about the instances is to be specified on a case-by-case basis. The only identifiable disadvantage from a user perspective is that the user has to replicate the pragmas for each instance to which they ought to apply, which may well be true for the use of most such generics. The rules for pragmas on generic subprograms already imply this alternative, so that no changes are required in that respect. The anomaly of pragma INLINE applying to instances as well is based on an explicit semantic rule of the pragma rather than a general rule of the language (and hence not really an anomaly, merely a potential surprise). From an implementation perspective, Alternative 2 is a minor problem for those implementations that subscribe to the expansion model for implementing generics. The "current instance rule" comes natural to such an expansion (due to its systematic replacement of bound names), while a rule that limits the effect of the pragma to the generic declaration only will require special processing. The usage aspects outlined above outweigh this minor complication for implementations. !appendix 95-06-25 !section 12.3(14) !section 12.3(13) !section 10.1.5(3) !section 10.1.5(7) !subject Do library unit pragmas in generics apply to all instances ? !reference RM95-12.3(14);6.0 !reference RM95-12.3(13);6.0 !reference RM95-10.1.5(3);6.0 !reference RM95-10.1.5(7);6.0 !keywords library unit pragma !from Erhard Ploedereder 4-12-95 !reference as: 95-5122.a Erhard Ploedereder 95-4-11>> A three-part question: Part I: Library unit pragmas are legal only if they apply to library units - 10.1.5(7). If such a pragma is given within a generic package, the argument name necessarily denotes the generic package itself, which must be a library unit. The "current instance rule" of 12.3(14) implies that in an instantiation the name denotes the current instance; the pragma therefore applies to the current instance of the instantiation. It follows that generic units containing a library unit pragma can only be instantiated as library units; other instantiations are illegal due to 10.1.5(7). Is this a correct conclusion ? --------------------- Part II: The interpretation gets murkier, when asking the same question for library unit pragmas without argument name. In this case, 12.3(14) does not apply, when literally interpreted. Is 12.3(13) sufficient to come to the same conclusion, namely that the pragma applies to the current instance in an instantiation ? -------------------------------- Part III: Under the above interpretation, 10.1.5(3-6) makes it impossible to have a library pragma apply to a generic package only but not to its instances. Would this ever be necessary/desirable ? (Interestingly, the rules do not prevent this for generic subprograms.) Note: For some of the predefined library pragmas, 10.1.5(3-6) has its benefits: It prevents the inverse situation to the question above: no pragma for the generic unit, but pragmas for the instantiations. This would open a hole in the contract model: generic bodies would need to be rechecked upon instantiation. Example: Shared_Passive, due to E.2.1(9). **************************************************************** !section 12.3(14) !section 12.3(13) !section 10.1.5(3) !section 10.1.5(7) !subject Do library unit pragmas in generics apply to all instances ? !reference RM95-12.3(14);6.0 !reference RM95-12.3(13);6.0 !reference RM95-10.1.5(3);6.0 !reference RM95-10.1.5(7);6.0 !keywords library unit pragma !reference 95-5122.a Erhard Ploedereder 4-12-95 !from Tucker Taft 94-04-12 !reference as: 95-5124.a Tucker Taft 95-4-12>> !discussion > A three-part question: > > Part I: > > Library unit pragmas are legal only if they apply to library units - > 10.1.5(7). If such a pragma is given within a generic package, the argument > name necessarily denotes the generic package itself, which must be a library > unit. The "current instance rule" of 12.3(14) implies that in an > instantiation the name denotes the current instance; the pragma therefore > applies to the current instance of the instantiation. > > It follows that generic units containing a library unit pragma can > only be instantiated as library units; other instantiations are illegal > due to 10.1.5(7). > > Is this a correct conclusion ? No, that was not the intent. The legality rule requiring a library unit pragma to denote the declaration of a library unit is not intended to disallow a generic library unit with such a pragma to be instantiated as a nested unit. Some clarification may be appropriate, however, to be language-lawyerly... Paragraph 10.1.5(7) doesn't say a library unit pragma must denote a library unit, but rather that it must denote the *declaration* of a library unit. There is a subtle difference here (see 8.6(16-18)). When inside a generic, the name of the generic still denotes the *declaration* of the generic, though the *entity* it denotes is the current instance of the generic. This subtle language-lawyerly difference between what "declaration" is denoted vs. what "entity" is denoted is only important in a few places, but is definitely relevant when talking about current instance-related rules. In any case, it wouldn't hurt to be more explicit in 10.1.5(7) about generic library units. > Part II: > > The interpretation gets murkier, when asking the same question for library > unit pragmas without argument name. In this case, 12.3(14) does not apply, > when literally interpreted. Is 12.3(13) sufficient to come to the same > conclusion, namely that the pragma applies to the current instance in an > instantiation ? That was not the intent. In general, a library unit pragma that applies to a generic library unit does not necessarily apply to all instances of the generic unit. > Part III: > > Under the above interpretation, 10.1.5(3-6) makes it impossible to have a > library pragma apply to a generic package only but not to its > instances. Would this ever be necessary/desirable ? > (Interestingly, the rules do not prevent this for generic subprograms.) As indicated above, it was the intent that a library unit pragma only apply to the generic unit itself, not automatically to its instances. > Note: > For some of the predefined library pragmas, 10.1.5(3-6) has its benefits: It > prevents the inverse situation to the question above: no pragma for the > generic unit, but pragmas for the instantiations. This would open a hole in > the contract model: generic bodies would need to be rechecked upon > instantiation. Example: Shared_Passive, due to E.2.1(9). I don't follow. A Shared_Passive library unit may only depend on other Pure or Shared_Passive library units. Why is your suggested (but unintended) interpretation of 10.1.5(3-6) useful here? In any case, a library unit pragma should be reapplied to the instantiation of a generic unit if you want it to apply to the instance. -Tuck **************************************************************** !section 12.3(14) !section 12.3(13) !section 10.1.5(3) !section 10.1.5(7) !subject Do library unit pragmas in generics apply to all instances ? !reference RM95-12.3(14);6.0 !reference RM95-12.3(13);6.0 !reference RM95-10.1.5(3);6.0 !reference RM95-10.1.5(7);6.0 !keywords library unit pragma !reference 95-5122.a Erhard Ploedereder 4-12-95 !reference 95-5124.a Tucker Taft 95-4-12 !from Erhard Ploedereder !reference as: 95-5128.a Erhard Ploedereder 95-4-13>> !discussion I wrote: > Note: > For some of the predefined library pragmas, 10.1.5(3-6) has its benefits: It > prevents the inverse situation to the question above: no pragma for the > generic unit, but pragmas for the instantiations. This would open a hole in > the contract model: generic bodies would need to be rechecked upon > instantiation. Example: Shared_Passive, due to E.2.1(9). Tuck responded: > I don't follow. A Shared_Passive library unit may only depend on > nother Pure or Shared_Passive library units. Why is your suggested > (but unintended) interpretation of 10.1.5(3-6) useful here? Indeed, the note was incorrect as written. The "problem" I was worried about exists already (and is independent of the topic of this comment). Clearly, I can already have a generic unit without the XYZ Pragma and then apply the XYZ Pragma to instantiations. Assume further that the XYZ Pragma imposes restrictions on the contents of the unit body, as most of the predefined library unit pragmas do. The semantics of the predefined pragmas are carefully designed to prevent the need for reexamining the body of the generic unit by individually imposing the rule that units depended on must be at least as restrictive, in particular the generic unit itself that gets instantiated. However, this is not required as an inherent semantics of program unit pragmas. Consequently, an impl.-defined pragma need not have a similar semantic rule. In that case, the enforcement of the restriction requires reexamination of the body of the instantiation, which may determine the body to be illegal. I suppose this is an "implementor beware!" situation, rather than a language issue. **************************************************************** From ploedere@grimm.informatik.uni-stuttgart.de Tue Jul 11 19:09:43 1995 Return-Path: Received: from inmet.camb.inmet.com by dsd.camb.inmet.com (4.1/SMI-4.1) id AA09334; Tue, 11 Jul 95 19:09:43 EDT Received: from sw-eng.falls-church.va.us (ns1.sw-eng.falls-church.va.us) by inmet.camb.inmet.com (4.1/SMI-4.1) id AA02149; Tue, 11 Jul 95 19:09:41 EDT Received: from ifi.informatik.uni-stuttgart.de by sw-eng.falls-church.va.us (8.6.11/) id XAA24672; Tue, 11 Jul 1995 23:10:41 GMT Received: from grimm.informatik.uni-stuttgart.de by ifi.informatik.uni-stuttgart.de with SMTP; Wed, 12 Jul 95 01:09:35 +0200 Received: by grimm.informatik.uni-stuttgart.de with SMTP; Wed, 12 Jul 1995 01:09:56 +0200 Received: by hesse.progsprach.informatik (5.x/SMI-SVR4) id AA09656; Wed, 12 Jul 1995 01:09:38 +0200 Date: Wed, 12 Jul 1995 01:09:38 +0200 From: Ploedereder@informatik.uni-stuttgart.de (Erhard Ploedereder) Message-Id: <9507112309.AA09656@hesse.progsprach.informatik> To: ada-comment@sw-eng.falls-church.va.us Subject: DRAFT of AI95-00041 !topic DRAFT of AI95-00041; Does <> for a formal subprogram default freeze the actual ? <> !discussion !standard 13.14 (05) 95-06-25 AI95-00040/00 !class confirmation 95-06-25 !status received 95-06-25 !subject Does <> for a formal subprogram default freeze the actual ? !summary 95-06-25 A box for a formal subprogram_default freezes the actual subprogram determined in an instantiation. !question 95-06-25 Consider: type T is .... type T2 is ... function "+"(A: T; B: T2) return T; generic type FT is private; with function "+"(A: FT; B: T2) return FT is <>; package GP is ... package IP is new GP(T); -- does this instantiation freeze "+" and therefore T2 ? I presume this is intended, but 13.14(5) doesn't cover that case. !response 95-06-25 ARM 12.6(10): "If a generic unit has a subprogram_default specified by a box, and the corresponding actual parameter is omitted, then it is equivalent to an explicit actual parameter that is a usage name identical to the defining name of the formal." Thus, the instantiation GP(T) is equivalent to the instantiation GP(T, "+"). ARM 13.14 (4,5,14) then demand that "+" and T2 are frozen by the instantiation. !appendix 95-06-25 !section 13.14(5) !section 12.6(10) !subject Does <> for a formal subprogram default freeze the actual ? !reference RM95-13.14(5) !from Erhard Ploedereder 4-11-95 !keywords freezing !reference as: 95-5120.a Erhard Ploedereder 95-4-10>> !discussion Consider: type T is .... type T2 is ... function "+"(A: T; B: T2) return T; generic type FT is private; with function "+"(A: FT; B: T2) return FT is <>; package GP is ... package IP is new GP(T); -- does this freeze "+" and therefore T2 ? I presume this is intended, but 13.14(5) doesn't cover that case. **************************************************************** !section 13.14(5) !section 12.6(10) !subject Does <> for a formal subprogram default freeze the actual ? !reference RM95-13.14(5) !reference RM95-12.6(10);6.0 !reference 95-5120.a Erhard Ploedereder 4-11-95 !keywords freezing !from Tucker Taft 95-04-11 !reference as: 95-5121.a Tucker Taft 95-4-11>> !discussion > Consider: > > type T is .... > type T2 is ... > function "+"(A: T; B: T2) return T; > > generic > type FT is private; > with function "+"(A: FT; B: T2) return FT is <>; > package GP is ... > > package IP is new GP(T); -- does this freeze "+" and therefore T2 ? Yes. > I presume this is intended, but 13.14(5) doesn't cover that case. Per 12.6(10), the instantiation GP(T) is equivalent to the instantiation GP(T, "+"). Of course, we all know that "equivalent" generally means "similar to but not exactly the same in some confusing way" but at least in this case, the intent was that they really are equivalent! At least a NOTE would help here I suppose to make it clear that the "equivalence" is really an equivalence. -Tuck ****************************************************************