!standard 12.07(0) (00) 99-07-28 AI95-00086/04 !class confirmation 95-08-19 !status WG9 approved (8-0-0) 97-07-04 !status ARG approved (5-0-2) 97-04-11 !status work item 95-08-19 !status received 95-08-19 !priority Medium !difficulty Hard !subject Passing generic formal packages with (<>) !summary If a generic formal package B whose actual part is (<>) is passed as an actual to another generic formal package A without (<>), then 12.7(5-8) requires the actuals of B to match the actuals of A. For the purpose of this rule, the actuals of B are the entities denoted by names of the form B.x, where x is a generic formal parameter of B. !question If a generic formal package B whose actual part is (<>) is passed as an actual to another generic formal package A without (<>), then 12.7(5-8) requires the actuals of B to match the actuals of A. For the purpose of this rule, what are the actuals of B? !response 12.7(5-8) require the actual parameters of the actual package to match the actual parameters of the formal package. But if the actual package has (<>), then its actual parameters are denoted by the formal parameters. Consider the following illegal example: generic type T is private; package Template is X : T; end Template; with Template; generic type Ft1 is private; with package Formal_With_Actual is new Template( Ft1 ); package G1 is Y : Ft1 := Formal_With_Actual.X; end G1; with Template; generic type Ft2 is private; with package Formal_With_Box is new Template( <> ); package G2 is package I3 is new G1( Ft2, Formal_With_Box ); -- Illegal! end G2; The above is illegal, because the actual for Formal_With_Box is Formal_With_Box.T, and this does not statically match Ft2 (or anything else). Note that if the above were legal, the following would cause trouble: with Template, G2; package Instantiator is package I1 is new Template( Integer ); package I2 is new G2( Boolean, I1 ); end Instantiator; because I2 contains a variable (Y) of type Boolean, initialized to I1.X, which is of type Integer. Note that we cannot defer the check until instantiation time, because I3 could be in the *body* of G2 (instead of in the spec, as shown above), and this would constitute a contract model violation. Now, consider the following legal example: generic type T1 is private; package G1 is ... end G1; generic type T2 is private; with package FP2 is new G1(T2); package G2 is ... end G2; generic with package FP3 is new G1(<>); package G3 is package I2 is new G2(T2 => FP3.T1, FP2 => FP3); -- OK. ... end G3; The instantiation I2 is legal because the actual for T2 is FP3.T1, which matches FP3.T1. !ACATS test Create a B-Test and a C-Test with the examples in this ruling. !appendix !section 12.7(0) !subject Generic Contract Model Violation ? !reference AARM95-12.7;6.0 !from Jesper Joergensen 95-08-16 !reference as: 95-5257.a Jesper Joergensen 95-8-16>> !discussion The use of a formal package as an actual to another formal package is a quite complex matter and as far as I can see we have a contract model violation with the present rules. Consider the example (I'm sorry, but I don't think this example can be shorter): -- first the "template" in the sense of [AARM 12.7(4)]: generic type T is private; package Template is X : T; end Template; -- then a formal package using the template: with Template; generic type Ft1 is private; with package Formal_With_Actual is new Template( Ft1 ); package G1 is Y : Ft1 := Formal_With_Actual.X; end G1; -- then another formal package using the template: with Template; generic type Ft2 is private; with package Formal_With_Box is new Template( <> ); package G2 is pragma Elaborate_Body; -- just to make a body for G2 legal end G2; -- then a unit instantiating G2: with Template, G2; package Instantiator is package I1 is new Template( Integer ); package I2 is new G2( Boolean, I1 ); end Instantiator; -- so far nothing is wrong (all legality rules are fulfilled), but if the -- body of G2 contains an instantiation of G1 using its own formal -- parameters as the actuals, we have a problem: with G1; package body G2 is package I3 is new G1( Ft2, Formal_With_Box ); end G2; This is a legal instantiation as far as I can see. The result of all this is that we have a package instance I2 with the following contents: package I2 is pragma Elaborate_Body; end I2; package body I2 is -- package I3 is new G1( Boolean, I1 ): package I3 is Y : Boolean := I1.X; end I3; end I2; And here we have a boolean variable initialized to that of an integer value! because we have associated the formal type T with both of these types. 1. Is the above analysis correct ? 2. If yes, don't we need a legality rule that forbids using a formal package with a box as an actual package for a formal package without box. As far as I can see this kind of instantiation is the only one requiring an extra check in an instance (for an enclosed instance) for the rules 12.7(6-8). In all other cases we only need to check for these rules at the place of the individual instantiations. In the context of the above example, we can't check the rules at the place of G2.I3 because we still don't know the actuals for Formal_With_Box. /Jesper, DDC-I **************************************************************** !section 12.7(00) !subject Generic Contract Model Violation ? !reference AARM95-12.7;6.0 !reference 95-5257.a Jesper Joergensen 95-08-16 !from Tucker Taft 95-08-16 !reference as: 95-5260.a Tucker Taft 95-8-17>> !discussion > The use of a formal package as an actual to another formal package is a quite > complex matter and as far as I can see we have a contract model violation with > the present rules. Consider the example (I'm sorry, but I don't think this > example can be shorter): > > > -- first the "template" in the sense of [AARM 12.7(4)]: > > generic > type T is private; > package Template is > X : T; > end Template; > > > -- then a formal package using the template: > > with Template; > generic > type Ft1 is private; > with package Formal_With_Actual is new Template( Ft1 ); > package G1 is > Y : Ft1 := Formal_With_Actual.X; > end G1; > > > -- then another formal package using the template: > > with Template; > generic > type Ft2 is private; > with package Formal_With_Box is new Template( <> ); > package G2 is > pragma Elaborate_Body; -- just to make a body for G2 legal > end G2; > > > -- then a unit instantiating G2: > > with Template, G2; > package Instantiator is > package I1 is new Template( Integer ); > package I2 is new G2( Boolean, I1 ); > end Instantiator; > > > -- so far nothing is wrong (all legality rules are fulfilled), but if the > -- body of G2 contains an instantiation of G1 using its own formal > -- parameters as the actuals, we have a problem: > > with G1; > package body G2 is > package I3 is new G1( Ft2, Formal_With_Box ); This violates 12.7(5), since the actual parameter of the "instance" Formal_With_Box is Formal_With_Box.T, and this does not statically match Ft2. > end G2; > > This is a legal instantiation as far as I can see. No, it violates 12.7(5). When inside a generic, a formal-package-with-box F looks like an instance whose actual parameters are F.formal1, F.formal2, etc. These "actual" parameters only match themselves for the purposes of 12.7(6..8), since nothing else is known about them. Perhaps an explicit clarification of this in the RM would be helpful. > ... > 1. Is the above analysis correct ? No. > ... > /Jesper, DDC-I -Tuck **************************************************************** !section 12.7(00) !subject Generic Contract Model Violation ? !reference AARM95-12.7;6.0 !reference 95-5257.a Jesper Joergensen 95-8-16 !from Jesper Joergensen 95-08-16 !reference as: 95-5261.a Pascal Leroy 95-8-17>> !discussion > -- first the "template" in the sense of [AARM 12.7(4)]: > > generic > type T is private; > package Template is > X : T; > end Template; > > -- then a formal package using the template: > > with Template; > generic > type Ft1 is private; > with package Formal_With_Actual is new Template( Ft1 ); > package G1 is > Y : Ft1 := Formal_With_Actual.X; > end G1; > > -- then another formal package using the template: > > with Template; > generic > type Ft2 is private; > with package Formal_With_Box is new Template( <> ); > package G2 is > pragma Elaborate_Body; -- just to make a body for G2 legal > end G2; > > -- so far nothing is wrong (all legality rules are fulfilled), but if the > -- body of G2 contains an instantiation of G1 using its own formal > -- parameters as the actuals, we have a problem: > > with G1; > package body G2 is > package I3 is new G1( Ft2, Formal_With_Box ); > end G2; > > This is a legal instantiation as far as I can see. The result of all this is > that we have a package instance I2 with the following contents: I may have an overly optimistic reading of the RM, but this instantiation seems illegal to me. RM95 12.7(5) states that "each actual parameter of the actual instance shall match the corresponding actual parameter of the formal package". In addition, RM95 12.3(3-4) indicates that actual parameters are provided by a generic_actual_part. Now the syntax in RM95 12.7(3) clearly says that "(<>)" is _not_ a generic_actual_part. >From these rules I draw the conclusion that your Formal_With_Box has no actual parameters, and therefore that the instantiation I3 is illegal, because the actual parameters don't match the formal parameters. Note that following this reasoning, I3 would be legal if Template had an empty generic_formal_part: Formal_With_Actual would have an empty generic_actual_part, and in this case the actual parameters of Formal_With_Box would match those of Formal_With_Actual. But I don't see that you could come up with a contract model violation with empty formal parts... > 1. Is the above analysis correct ? > 2. If yes, don't we need a legality rule that forbids using a formal package > with a box as an actual package for a formal package without box. As far as > I can see this kind of instantiation is the only one requiring an extra > check in an instance (for an enclosed instance) for the rules 12.7(6-8). > In all other cases we only need to check for these rules at the place of > the individual instantiations. In the context of the above example, we > can't check the rules at the place of G2.I3 because we still don't know > the actuals for Formal_With_Box. Even if your analysis was correct (which I doubt), it would not be a good idea to do the check in the instance. If we want to avoid all sorts of nasty dependences on the contents of the generic bodies, the check must be done at the place of G2.I3, "assuming the worst" (as is already the case for other rules). Pascal. _____________________________________________________________________ Pascal Leroy +33.1.30.12.09.68 pleroy@rational.com +33.1.30.12.09.66 FAX ****************************************************************