!standard 12.7 (05) 99-04-01 AI95-00213/03 !standard 12.7 (06) !class binding interpretation 98-11-30 !status ARG Approved (with changes) 9-0-0 99-03-24 !status work item 98-11-23 !priority High !difficulty Medium !subject Formal object matching for formal packages. !summary For a generic formal object of mode in, the rule in clause 12.7(6) is applied to the actual parameter of the actual instance, and the actual parameter for the formal package. If the actual parameter for the formal package is itself a formal parameter (of another generic unit), the actual for that parameter is used for matching. The latter rule is applied recursively. !question For a generic formal object of mode in, the rule in clause 12.7(6) defines a matching rule for actuals of generic formal packages. If the type of such an object is a type which cannot have static expressions (such as a tagged type), can the actuals ever match? (Yes.) An actual for an instance denotes a new-stand alone constant initialized by the actual to the instantiation, as described in 12.4(10). Therefore, the actuals for a formal package can never statically denote the same constant. Is this correct? (No.) Here is an example: package Pack is type Count_Type is tagged record; Count : Integer := 0; end record; TC_Default_Count : constant Count_Type := (Count => 0); end Pack; generic type Item (<>) is tagged private; TC_Default_Value : Item; package Test_0 is ... end Test_0; with Test_0; generic type Item_Type (<>) is tagged private; Default : Item_Type; with package Stacker is new Test_0 (Item_Type, Default); procedure Test_1 (S : in out Stacker.Stack; I : in Item_Type); with Pack; with Test_0; pragma Elaborate (Test_0); package Test_2 is new Test_0 (Pack.Count_Type, Pack.TC_Default_Count); procedure Test is package Count_Stacks renames Test_2; procedure TC_Count_Test is new Test_1 (Pack.Count_Type, Pack.TC_Default_Count,Count_Stacks); -- Legal? (Yes.) ... end Test; Note that Test_2.Default denotes a constant initialized by Pack.TC_Default_Count, while TC_Count_Test.TC_Default_Value denotes Pack.TC_Default_Count. Do these match by the rule of 12.7(6)? (Yes.) !recommendation The intent of the standard is that actuals are always used for the matching rule of 12.7(6). In addition, the intent is that formals denote the associated actual for the purposes of the matching rule of 12.7(6). !wording Add this paragraph after 12.7(8): For the purposes of matching, any actual parameter which is the name of a formal object is replaced by the formal object's actual expression (recursively). !discussion The intent of the standard is that actual objects are always used for the matching rule of 12.7(6). In addition, the intent is that formal objects used as actual parameters are ignored for the purposes of the matching rule of 12.7(6). Using formal objects as the actual parameter for a formal package is a natural way to use formal packages. In addition, all existing Ada compilers already support matching ignoring formal objects (as one of the validation tests required this behavior). If the strict language in the standard was followed, this example would be illegal. Indeed, any use of a formal object as an actual for a formal object of mode in to a formal package would be illegal by 12.7(6). This would require a substantial restructuring of formal packages if adding a formal object was necessary. In some cases, no workaround is available. In addition, existing code may depend on this feature, since compilers have supported it for at least four years. The revised rule is written in terms of eliminating all formal objects used directly as actuals, in order to avoid confusion. Other rules about which formal objects are eliminated could be considered (only local objects, only a single object, etc.) but these do not make the language easier to implement, just more confusing for the user. !appendix From: Randy Brukardt Sent: Saturday, November 21, 1998 7:47 PM Subject: Generic formal package matching. Here is a petition against an ACATS test: CC50A01 When a generic unit declares, in its generic formal part, a formal package with a generic_actual_part (as opposed to "(<>)"), the rules governing which instances are legal as an actual parameter (RM 12.7(6)) are quite strict when the generic_package_name mentioned in the formal package has formal objects. In particular, if the formal object is of mode IN, then the actual in the formal package and the actual in its matching actual package must be static expressions with the same value, or statically denote the same constant, or both be the literal null. The generic package CC50A01_0 has a formal object of mode IN in its generic formal part. This generic package is used as the generic_package_name in the formal package Stacker in generic CC50A01_1. The generic package CC50A01_1 is then instantiated twice as CC50A01.TC_Count_Test and as CC5 0A01.TC_Person_Test. Included is an abbreviated version of the test: package FC50A00 is type Count_Type is tagged record; Count : Integer := 0; end record; type Person_Type (Stat : Status; NameLen, AddrLen : Str_Len) is tagged record ... end record; TC_Default_Count : constant Count_Type := (Count => 0); TC_Default_Person : constant Person_Type := ...; end FC50A00; generic type Item (<>) is tagged private; TC_Default_Value : Item; package CC50A01_0 is ... end CC50A01_0; with CC50A01_0; generic type Item_Type (<>) is tagged private; Default : Item_Type; with package Stacker is new CC50A01_0 (Item_Type, Default); procedure CC50A01_1 (S : in out Stacker.Stack; I : in Item_Type); with FC50A00; with CC50A01_0; pragma Elaborate (CC50A01_0); package CC50A01_2 is new CC50A01_0 (FC50A00.Count_Type, FC50A00.TC_Default_Count); with FC50A00; with CC50A01_0; pragma Elaborate (CC50A01_0); package CC50A01_3 is new CC50A01_0 (FC50A00.Person_Type, FC50A00.TC_Default_Person); procedure CC50A01 is package Count_Stacks renames CC50A01_2; package Person_Stacks renames CC50A01_3; procedure TC_Count_Test is new CC50A01_1 (FC50A00.Count_Type, FC50A00.TC_Default_Count,Count_Stacks); procedure TC_Person_Test is new CC50A01_1 (FC50A00.Person_Type, FC50A00.TC_Default_Person,Person_Stacks); ... end CC50A01; For TC_Count_Test, the value FC50A00.TC_Default_Count is specified for Default. Therefore Default becomes a stand-alone constant initialized to the value of FC50A00.TC_Default_Count by RM 12.4(10). Default is the actual for the formal object TC_Default_Value in the formal package Stacker. The actual for the formal package Stacker is Count_Stacks, which is a rename of CC50A01_2. Its actual for the formal object TC_Default_Value is FC50A00.TC_Default_Count. For Count_Stacks to be a legal actual for the formal package Stacker, then the actuals corresponding to each of their formal objects TC_Default_Count must be static expressions with the same value, or they must statically denote the same constant, or they must both be the literal null. Obviously, neither is the literal null. Also, neither is a static expression because they are both of tagged record types, and RM 4.9(24) in conjunction with 4.9(5) considers only those constants initialized with static scalar or string expressions to be static expressions. Finally, they do not statically denote the same constant. The actual for Count_Stacks denotes the object FC50A00.TC_Default_Count, whereas the actual for Stacker denotes Default, which is a new stand-alone constant merely initialized to the value of FC50A00.TC_Default_Count. Because of this, the following diagnostic is issued: 289: procedure TC_Count_Test is new CC50A01_1 (FC50A00.Count_Type, 290: FC50A00.TC_Default_Count, 291: Count_Stacks); A ---------------------------------------------^ A:error: RM 12.7(6): formal package actual mismatch for formal "in" object tc_default_value An analogous argument holds for CC50A01.TC_Person_Test. The value FC50A00.TC_Default_Person is specified for Default. Therefore Default becomes a stand-alone constant initialized to the value of FC50A00.TC_Default_Person by RM 12.4(10). Default is the actual for the formal object TC_Default_Value in the formal package Stacker. The actual for the formal package Stacker is Person_Stacks, which is a rename of CC50A01_3. Its actual for the formal object TC_Default_Value is FC50A00.TC_Default_Person. For Person_Stacks to be a legal actual for the formal package Stacker, then the actuals corresponding to each of their formal objects TC_Default_Person must be static expressions with the same value, or they must statically denote the same constant, or they must both be the literal null. Obviously, neither is the literal null. Also, neither is a static expression because they are both of tagged record types, and RM 4.9(24) in conjunction with RM 4.9(5) considers only those constants initialized with static scalar or string expressions to be static expressions. Finally, they do not statically denote the same constant. The actual for Person_Stacks denotes the object FC50A00.TC_Default_Person, whereas the actual for Stacker denotes Default, which is a new stand-alone constant merely initialized to the value of FC50A00.TC_Default_Person. Because of this, the following diagnostic is issued: 295: procedure TC_Person_Test is new CC50A01_1 (FC50A00.Person_Type, 296: FC50A00.TC_Default_Person, 297: Person_Stacks); A ----------------------------------------------^ A:error: RM 12.7(6): formal package actual mismatch for formal "in" object tc_default_value We request that this test be withdrawn. ACAA analysis: My first reaction to this petition is ugh - if the petition is correct, the use of formal packages is greatly restricted Once getting past this, I found that the operative part is: "Finally, they do not statically denote the same constant. The actual for Count_Stacks denotes the object FC50A00.TC_Default_Count, whereas the actual for Stacker denotes Default, which is a new stand-alone constant merely initialized to the value of FC50A00.TC_Default_Count." Since the TC_Default_Count IS a constant, the only question is whether this interpretation that IN formals never denote their argument is correct. Certainly, none of the previous 46 conformity assessments using ACATS 2.1 (or ACVC 2.1) has found a problem here. In addition, such an interpretation is tantamount to claiming that formal IN parameters of composite types can never be used in generic formal packages. That's clearly silly. I would prefer to reject this petition for the above reasons, but I can't find a reason in the standard to do so. The implementors description of the meaning of an IN generic object is completely accurate. Clearly, this is an issue very much like the old Ada 83 issue of type A is new Integer range 1 .. 10; not being a static type. Randy. ************************************************************* From: Randy Brukardt Sent: Wednesday, November 25, 1998 3:31 PM Subject:Generic formal package matching. Here is an appeal of the resolution for this issue. Included here is the response from the ACAA: This message conveys the ACAA ruling for the (*Removed*) petition for ACVC 2.1 test program CC50A01. This petition is REJECTED. The implementor argues that the copy semantics defined in 12.4(10) means that actuals in the formal package never can denote the same constant. The wording in paragraphs in 12.7(5) and 12.7(6) was carefully constructed to insure that the actuals to the instantiations are used when applying 12.7(6), and not the copy defined by 12.4(10). The lengthy wording "the actual parameter of the actual instance" was used to insure that the meaning was unambiguous. If the implementors interpretation was used, none of the matching rules defined in 12.7(6) would be meaningful. The "stand-alone constant object" of 12.4(10) cannot be a static expression or the literal null anymore than it "denotes the same constant". Therefore, adopting the implementors interpretation makes 12.7(6) completely useless, and would make it impossible to use formal packages with formal object of mode in. Such a result is clearly nonsense, and could not have been intended by the language designers. Allowing this petition would create a dangerous incompatibility with other Ada compilers (all of the compilers tested to date pass this test). Finally, our response: The ACAA contends that 12.7(5) was worded in such a way that the actuals to instantiations are used when applying 12.7(6). We do not fully agree with this. We agree that the actuals to the formal package and the actuals to the actual instance are used when applying 12.7(6). But the text in 12.7(5-6) clearly does not apply to actuals of the containing instance (the instance to which the actual instance is an actual) or to any actuals of any instance other than the formal package and the actual instance. In particular, if the actual to the formal package is a copy created for a formal object in the same generic formal part as the formal package, then it does not apply to that copy for the formal object. In the example of TC_Count_Test, the phrase "actual parameter of the actual instance" is discussing the actual of Count_Stacks, or FC50A00.TC_Default_Count. But what is at issue is the actual parameter of the formal package. The actual parameter to the formal package is the copy made by 12.4(10). Again, for TC_Count_Test, this is the actual for TC_Count_Test.Stacker, which is TC_Count_Test.Default. There does not appear to be any rule to indicate that the actual corresponding to the formal object in the containing instance (which would be FC50A00.TC_Default_Count) should be used. We agree that this interpretation of 12.7(5-6) makes the matching rules for formal objects of mode "in" overly strict, although it doesn't quite make them meaningless. Formal packages are only unmatchable because of formal objects of mode "in" when a sibling formal object in the same generic formal part or an entity declared in a sibling formal package in the same generic formal part is used as the actual of the formal package. Implementing the matching rules in a less strict way is not difficult. It merely involves using the initial values of copies created for formal objects in the right circumstances. But because we can find no language rule that precisely specifies these circumstances, it is difficult to know where to draw the line and stop searching the initial value chains for an "ultimate actual". For instance, consider the following example: type tt is tagged null record; obj : tt; generic default : in tt; package g0 is copy : constant tt := default; end g0; generic default : in tt; with package f0 is new g0 (default); package g1 is ... end g1; generic default : in tt; with package f0 is new g0 (default); with package f1 is new g1 (f0.copy, f0); package g2 is ... end g2; package i0 is new g0 (obj); package i1 is new g1 (obj, i0); package i2 is new g2 (obj, i0, i1); Pretend that g2.f1 is a legal formal package and i1 is a legal instance. It is unclear whether or not i2 is a legal instance. In i2, 12.7(6) requires that the actual of the actual instance i1 (obj) must statically denote the same constant as the actual of the formal package i2.f1 (i2.f0.copy, or i0.copy), which is a constant initialized to the value of i0.default, which is a constant initialized to the value of its corresponding actual (obj). If the implementation followed this chain completely and used obj as the actual of the formal package, then i2 would be legal. But if the presence of a non-formal object in this chain of initializations indicates that the implementation should stop searching for the "ultimate actual", then i2 would be illegal. If the latter were the case, then consider a slightly more complicated example: type tt is tagged null record; obj : tt; generic default : in tt; package g0 is ... end g0; generic default : in tt; with package f0 is new g0 (default); package g1 is ... end g1; generic default : in tt; with package f0 is new g0 (<>); with package f1 is new g1 (f0.default, f0); package g2 is ... end g2; package i0 is new g0 (obj); package i1 is new g1 (obj, i0); package i2 is new g2 (obj, i0, i1); Again pretend that g2.f1 is a legal formal package and i1 is a legal instance. In i2, 12.7(6) requires that the actual of the actual instance i1 (obj) must statically denote the same constant as the actual of the formal package i2.f1 (i2.f0.default, or i0.default), which is a new constant initialized to the value of its actual (obj). In this case, the initialization chain contains only a single formal object. In some respects it is like the example in CC50A01. But in this example, the formal object is not of the containing instance as it was in TC_Count_Tests, but rather of a sibling formal package (i2.f0). So, should its initial value be used for the rule in 12.7(6) or not? If it should, then i2 would be legal. But if the presence of a formal object of an unrelated formal package indicates that the implementation should stop searching for the "ultimate actual", then i2 would be illegal. There are also cases that do not involve a third generic. Consider this example: type tt is tagged null record; obj : tt; generic default : in tt; package g0 is ... end g0; generic default1 : in tt; default2 : in tt := default1; with package f0 is new g0 (default2); package g1 is ... end g1; package i0 is new g0 (obj); package i1 is new g1 (obj, f0 => i0); In i1, 12.7(6) requires that the actual of the actual instance i0 (obj) must statically denote the same constant as the actual of the formal package i1.f0 (i1.default2), which is a constant whose initial value is i1.default1, which is another constant whose initial value is obj. So, if the second formal object's initial value should be used for 12.7(6), then i1 would be legal. But if the presence of a second formal object indicates that the implementation should stop searching for the "ultimate actual", then i1 would be illegal. Although we agree that our interpretation of 12.7(5-6) is possibly not the intent of the language designers, we do believe that it follows from the rules of the RM. Determining the precise intent of the language designers is a difficult matter in this case. We can imagine several different useful intents, including: * Initial values of any constants in the chain of initializations should be used. * Only initial values of copies of formal objects should be used. * Only initial values of copies of formal objects declared somewhere (possibly nested in another formal package) in the same generic formal part as the formal package should be used. * Only initial values of copies of formal objects declared immediately within the same generic formal part as the formal package should be used. * Only the first initial value of a copy of a formal object, if any, should be used. * No initial values of copies for formal objects should ever be used; the copy for the formal object should be used, itself. [The strict RM rule, and our interpretation.] We do not consider it appropriate for us to guess at the intent of the language designers, when there are so many possibilities. So, we repetition that this test be withdrawn until and unless an AI clarifies this issue. ************************************************************* From: Tucker Taft Sent: Wednesday, November 25, 1998 4:31 PM Subject:Re: Generic formal package matching. This time around, I agree with the petitioner. The thing I missed before was that there were two generic formal objects involved, not just one. If you stare at the source for cc50a01.a starting at line 188, you will see the following (with some slight changes to emphasize differences): generic type Item_Type ... Default : Item_Type; with package Stacker is new Gen_Pkg(Item_Type, Default); procedure Gen_Proc ... The point the petitioner is making is that the formal object "Default" above is used as the *actual* in the formal package declaration for Stacker. That is doomed to failure, since there could be no instantiation of Gen_Pkg (outside of the generic Gen_Proc itself) which could have an actual that statically denoted the constant "Default." The constant "Default" is simply not visible outside of Gen_Proc. "Default" is a new constant, created anew each time Gen_Proc is instantiated. I looked at our own Ada 95 front end implementation to figure out how we passed this test. This looks like a case where we trained our compiler to pass the tests. What we do when checking whether two actual-object expressions denote the same constant, is iterate, following across any number of formal object/actual object associations. This is clearly not justified by 12.7(6). So on review, I AGREE with the petitioner. To fix this test, you would have to change the generic procedure (Gen_Proc above, cc50a01_1 in the "real" test) to: generic with package Stacker is new Gen_Pkg(<>); use Stacker; procedure CC50A01_1 is ... and change the instantiations to only pass in the package, rather than passing in the item_type and the default as well. The original test construct should probably be incorporated into some B test at some point (not anytime soon, I hope). -Tuck ************************************************************* From: Randy Brukardt Sent: Wednesday, November 25, 1998 5:40 PM Subject: RE: Generic formal package matching. >If you stare at the source for cc50a01.a starting at line 188, >you will see the following (with some slight changes to emphasize >differences): > > generic > type Item_Type ... > Default : Item_Type; > with package Stacker is new Gen_Pkg(Item_Type, Default); > procedure Gen_Proc ... >The point the petitioner is making is that the formal object "Default" >above is used as the *actual* in the formal package declaration for Stacker. Yes...but this is the standard usage for generic formal packages. Are you saying that this was NOT intended to work??? I find that an incredible statement. >That is doomed to failure, since there could be no instantiation >of Gen_Pkg (outside of the generic Gen_Proc itself) which could have an actual >that statically denoted the constant "Default." The constant "Default" >is simply not visible outside of Gen_Proc. "Default" is a new constant, >created anew each time Gen_Proc is instantiated. Right, but then any useful use of a generic formal package with a generic In parameter is doomed to failure. Remember that this problem occurs for ALL uses of generic objects of mode in, not just objects of tagged types. If Item is some untagged record type, you've prevented the intended use of generic formal packages. Do you really expect the ARG to confirm the petitioners interpretation?? ************************************************************* From: Tucker Taft Sent: Wednesday, November 25, 1998 5:57 PM Subject:RE: Generic formal package matching. > Remember that this problem occurs for ALL uses of generic objects > of mode in, not just objects of tagged types. If Item is some untagged > record type, you've prevented the intended use of generic formal > packages. I don't see this at all. We simply have disallowed the use for generic formal packages with formal IN objects where the formal IN object is specified by an actual which is itself a generic formal IN object. So long as the actual for the object is not itself a generic formal, I don't see the problem. > Do you really expect the ARG to confirm the petitioners interpretation?? Yes. -Tuck ************************************************************* From: Randy Brukardt Sent: Wednesday, November 25, 1998 8:48 PM Subject:RE: Generic formal package matching. >The trick is always to put the formal package first, >and then use its actuals for specifying the rest of the formals. (We're getting into ARG territory here...) OK, so the point is that adding a formal object to a generic specification means that any uses of the package as a formal package not only need the object added, but probably will require wholesale restructuring. That is a REAL nice result. How would you use two formal packages together: generic type Item_Type ... Default : Item_Type; with package Stack_1 is new Gen_Pkg(Item_Type, Default); with package Stack_2 is new Gen_Pkg(Item_Type, Default); procedure Gen_Proc ... This is supposedly illegal. But if you use <>, you have two incompatible types. >I don't see this at all. We simply have disallowed the use for >generic formal packages with formal IN objects where the formal >IN object is specified by an actual which is itself a generic >formal IN object. So long as the actual for the object is not >itself a generic formal, I don't see the problem. The net effect is to make generic formal packages use <> in almost all cases where any object is used in the package. I can't think of any useful examples of a formal package which DIDN'T run into this problem. Most of the examples I've seen use this sort of construction, not <>. I would expect users to run into this error if they naturally extend the examples. >> Do you really expect the ARG to confirm the petitioners interpretation?? >Yes. I would expect the ARG to confirm current practice, which clearly is to allow it. I wonder if making this illegal would break existing user code. Is there any implementation reason why such matching cannot be done? (If there is, it probably would be in our compiler, so I suppose I don't know why I'm asking you!) (I'd like to get these answers for the AI). >-Tuck Randy. ************************************************************* From: Pascal Leroy Sent: Thursday, November 26, 1998 4:19 AM Subject: Re: Generic formal package matching. > This time around, I agree with the petitioner. Sure, formally the petitioner is doing exactly what the RM says. It's still the case that the RM is broken, but this is an ARG issue. > I looked at our own Ada 95 front end implementation to figure out > how we passed this test. This looks like a case where we > trained our compiler to pass the tests. What we do when checking > whether two actual-object expressions denote the same constant, > is iterate, following across any number of formal object/actual object > associations. This is clearly not justified by 12.7(6). We do exactly the same thing. I'm not sure if it's a case of training the compiler to pass the test, or simply making the language useful. As I said already, I don't like it, but I don't think we have any legal ground to reject the petition, especially if the implementer appeals. Note that all validated compilers look through formal-actual associations when checking 12.7(6). It is likely that there is code out there that takes advantage of this "enhancement." I don't think it's in this implementer's best interest to be legalistic: users who want to port code to this compiler will sooner or later run into this incompatibility. At any rate, a prompt ARG ruling would be useful. Pascal ************************************************************* From: Tucker Taft Sent: Thursday, November 26, 1998 7:30 AM Subject:Re: Generic formal package matching. Okay, now I think I understand both sides. I agree that the language is more useful if 12.7(6) is augmented to say something like: ... or if{, after passing through zero or more formal object/actual object associations,} they statically denote the same constant... and apparently all compilers thus far validated have done something like this. However, this added flexibility can in no way be read into the "official" RM words, IMHO. I also agree that there is probably more harm than good done at this point by requiring that all compilers remove this flexibility. Hence, I suggest we offer this vendor a choice: We may rule this test inapplicable to them, but they are required to add the flexibility to their compiler before their next validation (presuming a binding interpretation AI is imminent). Better, for uniformity's sake, we encourage them to add the flexibility to their compiler so they can pass this test, as all other validated compilers have already done. In any case, an AI is very much needed here. -Tuck ************************************************************* From: Randy Brukardt Sent: Monday, November 30, 1998 12:25 PM Subject:RE: Generic formal package matching. >In any case, an AI is very much needed here. I've already opened an AI, and I'll rewrite it to reflect this discussion. One point I forgot in my somewhat incoherent responses on Wednesday, is that the test in question was a 2.0.1 test - it wasn't even modified in version 2.1. So the support of this feature goes way back, which increases the likelyhood that some users are depending on it. ************************************************************* From: Tucker Taft[SMTP:stt@INMET.COM] Sent: Monday, November 30, 1998 5:24 PM Subject: Re: Revised AI-213. > ... > For a generic formal object of mode in, the rule in clause 12.7(6) is applied > to the actual parameter of the actual instance, and the actual parameter for > the formal package. If the actual parameter for the formal package is itself > a formal parameter (for another generic unit), the actual for that parameter > is used for matching. This wording should probably be made recursive, so that any number of formal/actual associations are followed. -Tuck *************************************************************