Version 1.14 of ais/ai-00317.txt
!standard 12.07 (03) 04-11-09 AI95-00317/10
!standard 12.07 (05)
!standard 12.07 (10)
!class amendment
!status Amendment 200Y 04-06-29
!status WG9 approved 04-11-18
!status ARG Approved 11-0-0 04-06-17
!status work item 04-06-07
!status Amendment 200Y 03-10-23
!status WG9 Approved 03-12-12
!status ARG Approved 8-0-2 03-10-04
!status work item 02-10-06
!status received 02-10-06
!priority Medium
!difficulty Easy
!subject Partial parameter lists for formal packages
!summary
A formal package may have a partially specified set of actual parameters.
!problem
When a generic has more than one formal package parameter, it is often
important to link the two packages via their actuals. However, the
only way to link the packages is to specify one with no actuals, and
specify the other with all of its actuals. For example:
generic
with package Inst1 is new Gen1(<>);
with package Inst2 is new Gen2(Inst1.A, Inst1.B, ...);
...
package GP is ...
The problem is that there may be some actuals of the second formal
package which are not linked to the first one. The only way to
deal with this is to add more formal parameters to the generic GP to
specify the values for the remaining actual parameters. For example:
generic
type T1 is private;
type T2 is private;
with package Inst1 is new Gen1(<>);
with package Inst2 is new Gen2(Inst1.A, Inst2.B, FT3 => T1, FT4 => T2);
...
package GP is ...
Unfortunately, this approach defeats much of the advantage of formal
package parameters, which is to reduce the number of formals and simplify
the usage of a generic.
!proposal
A formal package parameter may specify some, but not all, of its actual
parameters. For example:
generic
with package Inst1 is new Gen1(<>);
with package Inst2 is new Gen2(Inst1.A, Inst2.B, others => <>);
...
package GP is ...
The parameters which are not specified may be referenced by name as
expanded names using the formal package as its prefix. For example,
Inst2.FT3 and Inst2.FT4 may be used later in the formal generic part
of GP or within the specification or body of GP. By contrast, the specified
actuals may not be so named, to avoid confusion between the properties
of the actual and those of the formal.
Similarly, any implicit declarations associated with a given parameter
of the formal package may be named using the formal package as a
prefix only when the actual for the parameter is not specified.
With this proposal, the notation "(<>)" for its actual part is essentially
a short-hand for "(others => <>)."
!wording
Replace 12.7(3) with:
formal_package_actual_part ::=
([others =>] <>)
| [generic_actual_part]
| (formal_package_association {, formal_package_association}
[, others => <>])
formal_package_association ::=
generic_association
| generic_formal_parameter_selector_name => <>
Any positional formal_package_associations shall precede any named
formal_package_associations.
Replace 12.7(5) with the following:
The actual shall be an instance of the template. If the
formal_package_actual_part is (<>) or (OTHERS => <>), then the actual
may be any instance of the template; otherwise, certain of the actual
parameters of the actual instance shall match the corresponding actual
parameter of the formal package, determined as follows:
* If the formal_package_actual_part includes generic_associations
as well as associations with <>, then only the actual parameters
specified explicitly with generic_associations are required to match;
* Otherwise, all actual parameters shall match, whether the actual
parameter is given explicitly or by default.
The rules for matching of actual parameters between the actual instance
and the formal package are as follows:
Replace 12.7(10) with the following:
The visible part of a formal package includes the first list of
basic_declarative_items of the package_specification. In addition,
for each actual parameter that is not required to match, a copy of the
declaration of the corresponding formal parameter of the template is
included in the visible part of the formal package. If the copied
declaration is for a formal type, copies of the implicit declarations
of the primitive subprograms of the formal type are also included in
the visible part of the formal package.
For the purposes of matching, if the actual instance A is itself a
formal package, then the actual parameters of A are those specified
explicitly or implicitly in the formal_package_actual_part for A, plus, for
those not specified, the copies of the formal parameters of the
template included in the visible part of A.
!discussion
This is intended to be a natural generalization of the two capabilities
currently provided for specifying actual parameters of a formal package.
By providing this "mid-point" where some but not all of the parameters
are specified, the formal package capability becomes significantly more
useful, without measurably increasing the complexity of supporting the
capability.
The syntax is similar to that proposed for aggregates with <>. It requires
that individual defaulted parameters be given using named notation except
that others => <> with the usual meaning concerning all remaining parameters
may be used. Note, however, that avoiding others provides greater safety
when additional formal paramters are added since the programmer than has to
make an explicit choice as to whether a new formal parmater should be given
an explicit actual or <>.
There is an issue of which names are visible outside an instance:
generic
type T is new A;
--
type U is new B;
--
package GP is ... end GP;
generic
...
with package FP is new GP (T => T1, U => <>);
--
In the above, we suppose that F1 is an operation of A and so a
corresponding operation for T is implicitly declared, similarly we have an
implicitly declared operation F2 for U. The revised wording for the second
sentence of 12.7(10) clarifies that copies of the primitive operations for
the defaulted type U are visible whereas those for T are not. So we can
write FP.F2 but not FP.F1; however, since we have an explicit actual type T1
we can simply say T1.F1 anyway.
This AI also answers a related question. If a generic formal package A
whose actual part contains <> is passed as an actual to another generic
formal package B with at least some actuals specified, then the rules given
here require the actuals of A to match any specified actuals of B.
But what are the actuals of A which are given by "<>" in the definition of A?
Clearly, they should be the entities denoted by names of the form A.x, where x
is a generic formal parameter of A. These are the "copies of the
formal parameters of the template included in the visible part of A" mentioned
in the final sentence of 12.7(10).
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 ); --
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 of I3 until the instantiation of G2,
because I3 could be in the body of G2 (instead of in the specification,
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); --
...
end G3;
The instantiation I2 is legal by the following reasoning. The instantiation
I2 of G2 requires that the actual parameter corresponding to T2 of G2 is the
same as the type used for the instantiation of G1 which is the actual
package corresponding to FP2 of G2. In the instantiation I2, the package
corresponding to FP2 (the second parameter) is FP3 which is indeed an
instantiation of G1 and since it is with <>, the actual type for that
instantiation is simply denoted by FP3.T1; moreover, the actual type
corresponding to T2 (the first parameter) is explicitly given as T2 =>
FP3.T1 and so they are the same.
!example
Imagine a generic signature package with two formal parameters:
generic
type T is private;
Obj : T;
package Sig is end;
Now imagine there is a layered abstraction that wants two instances of this
signature, and wants them to share the same type T, but not necessarily the
same object "Obj".
generic
with package P1 is new Sig(<>);
with package P2 is new Sig(T => P1.T, Obj => <>);
package Layered_Abstraction is
X : P1.T := P2.Obj; --
--
--
--
...
end Layered_Abstraction;
Note that this exact situation came up during the design of a proposed physical
units AI (AI-324). We wanted to pull out some of the nested generics from the
large "System_Of_Units" generic. This would require the Unit_Signature generic
signature package to have at least one additional parameter, the
Names_Of_Dimensions:
generic
type Names_Of_Dimensions is (<>);
Name : in String;
Exponents : in Exponent_Array;
Scale_Factor : in Scale_Type;
type Value is digits <>;
package Unit_Signature is end;
But the use of these generics causes problems. If a "product" unit is
constructed from two individual units:
generic
with package Unit_A is new Unit_Signature(<>);
with package Unit_B is new Unit_Signature(Unit_A.Names_Of_Dimensions,
others => <>);
package Product_Unit is
type Value is ...
...
end Product_Unit;
It is necessary that the Names_Of_Dimensions types are the same. With the Ada
95 rule, we'd have to pass in all of the other parameters separately to be able
to force a match on just one of them:
generic
with package Unit_A is new Unit_Signature(<>);
Unit_B_Name : in String;
Unit_B_Exponents : in Exponent_Array;
Unit_B_Scale_Factor : in Scale_Type;
type Unit_B_Value is digits <>;
with package Unit_B is new Unit_Signature(Unit_A.Names_Of_Dimensions,
Unit_B_Name, Unit_B_Exponents, Unit_B_Scale_Factor, Unit_B_Value);
package Product_Unit is
type Value is ...
...
end Product_Unit;
This is clearly much less useful, and creates an asymmetric requirement
when instantiating, where information about Unit_A can be passed
in using a single signature instance, whereas Unit_B requires
four additional formal parameters and then a largely redundant
signature instance as well.
!corrigendum 12.7(3)
Replace the paragraph:
formal_package_actual_part ::=
(<>) | [generic_actual_part]
by:
formal_package_actual_part ::=
([others =>] <>)
| [generic_actual_part]
| (formal_package_association {, formal_package_association}, others => <>)
formal_package_association ::=
generic_association
| generic_formal_parameter_selector_name => <>
Any positional generic_associations shall precede any named
generic_associations.
!corrigendum 12.7(5)
Replace the paragraph:
The actual shall be an instance of the template. If the
formal_package_actual_part is (<>), then the actual may be any instance
of the template; otherwise, each actual parameter of the actual instance shall
match the corresponding actual parameter of the formal package (whether the
actual parameter is given explicitly or by default), as follows:
by:
The actual shall be an instance of the template. If the
formal_package_actual_part is (<>) or (others => <>), then the
actual may be any instance of the template; otherwise, certain of the actual
parameters of the actual instance shall match the corresponding actual
parameter of the formal package, determined as follows:
- If the formal_package_actual_part includes
generic_associations as well as associations with <
, then only the
actual parameters specified explicitly with generic_associations are
required to match;>
- Otherwise, all actual parameters shall match, whether the actual
parameter is given explicitly or by default.
The rules for matching of actual parameters between the actual instance
and the formal package are as follows:
!corrigendum 12.7(10)
Replace the paragraph:
The visible part of a formal package includes the first list of
basic_declarative_items of the package_specification. In addition,
if the formal_package_actual_part is (<>), it also includes the
generic_formal_part of the template for the formal package.
by:
The visible part of a formal package includes the first list of
basic_declarative_items of the package_specification. In addition,
for each actual parameter that is not required to match, a copy of the
declaration of the corresponding formal parameter of the template is
included in the visible part of the formal package. If the copied
declaration is for a formal type, copies of the implicit declarations
of the primitive subprograms of the formal type are also included in
the visible part of the formal package.
For the purposes of matching, if the actual instance A is itself a
formal package, then the actual parameters of A are those specified
explicitly or implicitly in the formal_package_actual_part for A, plus,
for those not specified, the copies of the formal parameters of the
template included in the visible part of A.
!ACATS test
Create ACATS tests to check this feature. Also, create B and C tests out
of the examples in the discussion.
!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
****************************************************************
From the editor, July 7, 2000
At the Potsdam ARG meeting (the 11th ARG meeting), it was decided that
AI-86 should not appear in the Records of Response, as it no one was able to
provide a explanation as to how the the conclusion follows from the existing
text of the RM. Moreover, we didn't feel capable to write that text at this
time.
AI-86 was be changed back to a work item, in order to either find an
appropriate explanation, or to decide on wording to implement the
recommendation (that is, a change in status from !confirmation to !binding
interpretation). [It was later folded into AI-317.]
****************************************************************
From: Tucker Taft
Semt: Sunday, September 28, 2003 3:41 PM
Here is an update to AI-317. Not much change.
I was supposed to add something to 12.7(10) to
fix a problem relating to "formal.formal.xxx"
but I can't remember the details.
Does anyone have a simple example to illustrate
the problem? I think Erhard brought it up
a few times, but the ARG minutes don't elaborate,
as far as I can see.
[Editor's note: This is version /03 of the AI.]
****************************************************************
From: Mario Amado Alves
Semt: Tuesday, September 30, 2003 1:04 PM
In Ada 95 the formal_package_actual_part is either the box or it must
list *all* the type parameters (Note 1). But sometimes a partial list
would be useful:
generic
type Formal_1 is private;
type Formal_2 is private;
...
package Template is ... end;
type Special_Actual is ...;
generic
with package Special_Template is
new Template
(Formal_1 => Special_Actual); -- PARTIAL LIST HERE (NOTE 2)
...
package Generic_Special_Unit is ... end;
package Special_Template is
new Template
(Formal_1 => Special_Actual, Formal_2 => ..., ...);
package Special_Unit is
new Generic_Special_Unit
(Special_Template, ...);
This only requires modification to 12.7. If there is interest I'll try
to formalize an AI. Thanks.
NOTES
1. See RM 12.7 (3). I don't find this required completness a clear
ramification, but that is another story.
2. Not Ada 95. Alternate syntaxes (also not Ada 95):
(Formal_1 => Special_Actual, <>);
(Formal_1 => Special_Actual, others => <>);
****************************************************************
From: Randy Brukardt
Semt: Tuesday, September 30, 2003 5:53 PM
This is AI-317. Please check for existing AIs before starting new
discussions; it just makes more work for me. (Of course, comments on
existing AIs are fine.)
****************************************************************
From: Mario Amado Alves
Semt: Tuesday, September 30, 2003 6:27 PM
Indeed it is! Thanks. I do search the AIs before posting, but on this
case it seems I missed it for some reason. Sorry.
****************************************************************
From: Tucker Taft
Semt: Monday, June 7, 2004 11:07 PM
Here is an update to AI 317 [This is version /06 of the AI - ED] that
includes the confirmation provided by AI-86 for the case when the actual
instance is itself a formal package. The only change was to add
the following paragraph at the end of 12.7:
For the purposes of matching, if the actual instance is itself a
formal package, then its actual parameters are those specified
explicitly or implicitly in the formal package actual part, plus, for
those not specified, the copies of the formal parameters of the
template included in the visible part of the actual instance.
That is admittedly quite a sentence. ;-)
****************************************************************
From: Randy Brukardt
Semt: Wednesday, June 9, 2004 10:42 PM
> Here is an update to AI 317 that includes the confirmation
> provided by AI-86 for the case when the actual instance is
> itself a formal package. The only change was to add
> the following paragraph at the end of 12.7:
I think it would be unfortunate to lose the examples and
discussion from AI-86 (which would happen as the AI would be
deleted since it was folded into AI-317). They would make good
ACATS tests, if nothing else. But since the problem is real and requires
wording to fix, it would be useful to explain the problem and the fix.
> For the purposes of matching, if the actual instance is itself a
> formal package, then its actual parameters are those specified
> explicitly or implicitly in the formal package actual part, plus, for
> those not specified, the copies of the formal parameters of the
> template included in the visible part of the actual instance.
>
> That is admittedly quite a sentence. ;-)
Sure is. I wonder what it means? :-) In particular, what's an "actual part"?
There's no such term in the Standard's index. Do you mean "actual parameter
list"? Or maybe you meant "formal_package_actual_part" (the syntactic entity).
****************************************************************
From: Tucker Taft
Semt: Thursday, June 10, 2004 12:06 AM
> I think it would be unfortunate to lose the examples and
> discussion from AI-86 (which would happen as the AI would be
> deleted since it was folded into AI-317). They would make good
> ACATS tests, if nothing else. But since the problem is real and requires
> wording to fix, it would be useful to explain the problem and the fix.
Can we just concatenate the AI-86 discussion and examples to
that of AI-317? I would think that would work with just a
bit of smoothing.
>> For the purposes of matching, if the actual instance is itself a
>> formal package, then its actual parameters are those specified
>> explicitly or implicitly in the formal package actual part, plus, for
>> those not specified, the copies of the formal parameters of the
>> template included in the visible part of the actual instance.
>>
>>That is admittedly quite a sentence. ;-)
>
>
> Sure is. I wonder what it means? :-) In particular, what's an
> "actual part"? There's no such term in the Standard's index. Do you mean
> "actual parameter list"? Or maybe you meant "formal_package_actual_part"
> (the syntactic entity).
The phrase "formal package actual part" should have been
the syntactic entity "formal_package_actual_part."
****************************************************************
Questions? Ask the ACAA Technical Agent