Version 1.1 of ais/ai-00041.txt
!standard 08.03 (16) 98-04-01 AI95-00041/08
!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 WG9 approved 96-12-07
!status ARG approved 12-0-0 96-10-07
!status ARG approved (subj. ed. rev., letter ballot was 12-0-0) 96-10-03
!status ARG-approved (9-0-0) 96-06-17; letter ballot pending
!status received 95-06-25
!reference AI95-00199
!priority High
!difficulty Hard
!subject Program unit pragmas in generic units
!summary 96-09-15
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 rule of the pragma specifies the contrary. The only language
defined pragma with such a rule is pragma Inline.
If the user wants a library unit pragma without such a rule to apply to
an instance, then that pragma 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.3(14) should read ({...} indicates added text): "...except in the case
of a name that denotes the generic_declaration or some declaration 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 96-05-28
See recommendation.
!discussion 96-09-15
Part I: The individual program unit pragmas
Some general observations:
1. If a pragma that applies to a generic unit were not to apply
to all instances, the user would still have the option to
specify such a pragma for each of the instances individually.
This may be cumbersome, but no language functionality is lost.
2. If a pragma that applies to a generic unit were to apply to
all instances automatically, the user would lose the
capability of specifying a pragma that applies to the generic
unit only.
Note that the user does not have the option of placing the
pragma outside the generic package and thereby escape a
"current instance rule" (discussed later) selectively, since
such placement is not allowed for pragmas on generic packages;
ARM 10.1.5(4).
Before discussing the language rules, we examine the pragma semantics for
all program unit pragmas and discuss whether or not the pragma should apply
to the generic unit only or to all its instances as well.
Pragma Preelaborate:
Consider the following example:
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, if the pragma applies to the instances as well, they would all
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.
If pragma Preelaborate applied to all instances, the user would no longer
have the means to force preelaboration of the body of the generic unit (as
shown in the example) without also imposing such preelaboration requirements
on all instances and restricting the instantiations to library level. (The
semantics of the pragma when applied to local instances is somewhat
ill-defined.)
We conclude that pragma Preelaborate should not automatically apply to all
instances of the generic unit.
Pragma Pure:
Consider the following example:
generic
type T is private;
package Q is
pragma Pure(Q);
type TN is new T;
...
end Q;
The user intention of pragma Pure in this package is to indicate that this
generic unit can (but need not) be instantiated to yield a pure
package. E.g.:
type Acc is access TT;
package Q_Acc is new Q(Acc); --
package Q_Int is new Q(Integer); --
pragma Pure(Q_Int);
If the pragma were applicable to all instances, the package Q_Acc would be
illegal.
This would put 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.
This reuse problem arises not only from the nature of the actual parameters
of the instantiation, but also (and more importantly) from the context
clauses of the instantiation, i.e.,
with P; --
package Q_Int2 is new Q(P.T); --
--
and from any non-pure context of a local instantiation (if local instances
were allowed at all, given that the pragma is a library unit pragma).
Among others, any predefined or implementation-defined pure generic packages
could not be instantiated in any non-pure context, which would be a quite
devastating consequence.
(A similar dilemma arises for all the other categorization pragmas when
used (or not used) in reusable generic packages.)
We conclude that pragma Pure definitely should not automatically apply to
all instances of the generic unit.
Pragmas Shared_Passive and Remote_Types:
These pragmas impose the necessary restrictions to create a shared passive
or a remote types library unit, respectively. As in the case of pragma
Pure, such a pragma for a generic unit is a precondition for any
instantiation to be so classified. However, unlike pragma Pure, it is not
quite as obvious why instances should not be automatically in the respective
category as well.
In the case of shared passive packages there is a potential issue when
an application may be required to execute in environments that may or
may not support storage nodes. If an instantiation is shared passive
then the library unit may only be assigned to a single partition. In
environments that do not support storage nodes this may be unnecessarily
restrictive since it is possible that a non-categorized instance can be
replicated in different partitions without compromising execution (e.g.,
if there are no variables in the package specification since a typical
use of shared passive packages may be to store constant data that are
common to different partitions).
In the case of remote types packages, one may wish to declare a type with
subprograms that may be accessed both locally and remotely depending upon
the instantiation. If the pragma applies to all instantiations then, when
any declared access type within the package is referenced, it must be
treated as containing a potentially remote access value. (This is
particularly relevant, if the implementation uses wide pointers to represent
remote access type values.)
One might perhaps surmise that despite the above scenarios, user convenience
might argue for automatically applying these pragmas to all instances. However,
we observe that no semantic difficulties arise if this were not the case and
that such implicit "inheritance" seems contrary to the principle that
critical specifications should be explicit. The cited situations show that
to a-priori preclude that reusable packages can be instantiated both in
restricted and unrestricted contexts may be unwise.
Pragma All_Calls_Remote, Remote_Call_Interface:
It is not unreasonable for applications to develop generic packages that may
be instantiated to provide both locally and remotely accessible
subprograms. For example, consider the case of a partition that provides the
same interface for both intra-partition and inter-partition clients. If an
instantiation is always a remote interface package, then intra-partition
clients will incur the cost of calling subprograms through a compiler
generated stub.
Additionally, a confirmation of the intent that this pragma should be
explicitly specified is present in AARM E.2.3(15b) where it is stated "We
considered making the public child of an RCI package implicitly RCI, but it
seemed better to require an explicit pragma to avoid any confusion." It
seems inconsistent to require an explicit pragma for a public child and not
require an explicit pragma for an instantiation.
We conclude that the pragma should be applicable to the generic unit only.
Pragma Elaborate_Body:
Pragma Elaborate_Body applied to generic library unit forces the elaboration
of the body of the unit immediately after the elaboration of the generic
declaration. In the case of instantiations, this effect of the pragma
merely restates the existing rules on instance elaboration, ARM 12.3(20), so
that this effect is the rule for instantiations in general. Hence, there is
no need to make the pragma apply automatically to all instances, while it
would be most detrimental to enforce as a secondary consequence that such
instantiations yield only library units.
We conclude that the pragma should be applicable to the generic unit only.
Pragmas Elaborate and Elaborate_All:
These pragmas are irrelevant for this discussion, as they refer to program
units other than the (generic) unit in which they appear. (Consequently, the
affected units are elaborated prior to the elaboration of the generic unit
and, hence, its instances.)
Pragmas Convention, Export, Import:
These pragmas are irrelevant, since they cannot be applied to generic units.
Pragma Inline:
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 on explicitly stated semantics of the pragma; ARM 6.3.2(5).
This concludes the list of predefined program unit pragmas. We have seen
that, in some cases, applicability of the pragma to all instances would be
seriously detrimental. We have seen other cases, where applicability to all
instances may be more convenient on occasion, but is neither absolutely
necessary nor warrants a rule that a-priori precludes reusable generic units
that can be instantiated in both restricted and unrestricted contexts.
Part II: The Language Rules
First, the relevant ARM paragraphs:
(The elisions ".." omit text irrelevant for the question at hand.)
12.3(11) provides the general rule for checking legality rules in generic
instantiations. The following discussion deals with these legality rules.
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) reaffirms 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.
(Irrespective of such literal reading of the standard, we note that surely
the semantics of a pragma without argument should not differ from the
semantics of the pragma naming the unit explicitly.)
We note in passing that the wording of 12.3(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.3(14) should be expanded to read "...except in the case of a name that
denotes the generic_declaration or some declaration 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.
Program unit pragmas applied to generic subprograms are not affected by the
current instance rule, since perforce 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 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.
This short exegesis of the ARM shows that there is no clear answer found in
the ARM to the questions at hand. In interpreting the standard, we
therefore can take three different routes:
1. confirm the "current instance rule", i.e., the pragma applies
to all instances.
2. confirm the rule that the pragma applies only to the generic unit
itself.
3. define the most appropriate rule for each pragma.
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.
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).
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. Some aggravatingly undesirable consequences have been shown
in the discussion of the individual pragmas.
Finally, if the main objective were 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. This
in turn is completely unacceptable, since, for example, it would prohibit
local instantiations of Unchecked_Conversion.
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.
Alternative 3: Individual rules for each pragma
We rejected this alternative to maintain some uniformity in the
interpretation of pragmas.
In the final analysis, alternative 2 appears to have the fewest
disadvantages and presents a uniform general rule, while still allowing
"overriding" special rules for individual pragmas, as in the case of pragma
Inline.
!appendix
!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.
****************************************************************
!section 08.03(16)
!subject Program unit pragmas in generic units
!reference AI95-00041
!reference RM95-08.03 (16)
!reference RM95-08.03 (18)
!reference RM95-10.01.05 (02)
!reference RM95-10.01.05 (07)
!reference RM95-12.03 (13)
!reference RM95-12.03 (14)
!reference RM95-E.2
!from Offer pazy 95-10-11
!reference as: 95-5326.a Offer Pazy 95-10-11>>
!discussion
I disagree with the recommendation suggested in this AI. First, from a
general point of view. I think that the idea that a generic is not known to
be OK until it is instantiated by its clients is flawed. What's the point
of developing generics if you can't rely on the clean compilation until to
point when users start to instantiate it. Also, if I understand (?!) the
issue
correctly, for implementation that do not use the macro-expansion approach,
this will represent a major problem, since after a generic unit has been
cleanly compiled, they rely on the contract model rules to check
instantiations and not on recompiling the generic unit.
But more specifically, I have a problem with applying the recommendation to
the categorization pragmas which are the creation of the DS annex. I find
it hard to believe that people will develop "general" generic units without
dedicating them as RCI or SP packages. Such a categorization is built
into the creation of the generic and into its contents. I don't think it
is practical to think about somebody writing such a generic unit and
letting its users (instantiators) later decide whether or not it should
serve as an RCI, SP, or a normal package. This is not the way I envision
people developing such generics. Again, it implies that the compiler will
have to check all the corresponding rules upon each instantiation on a unit
which may have long been developed and frozen in another program library.
So to summarize, I recommend (at least in the case of categ pragmas) a
rule which will say (and I thought it already clearly said that) that a
categ pragma can be placed inside a generic unit (and it takes effect).
Appling a categ pragma on the instance can only repeat that of the generic
unit (i.e. be a no-op) and not change the categorization of the instance.
Offer Pazy
31 Robinwood Ave.
Boston, MA 02130
USA
(617)522-5988
pazy@world.std.com
****************************************************************
!section 10.1.5(02)
!subject Program unit pragmas in generic units
!reference AI95-00041
!reference RM95-10.1.5(2-7)
!reference RM95-12.3(13-14)
!from Tucker Taft 95-10-30
!reference 95-5373.e Tucker Taft 95-10-30>>
!discussion
The background on this AI seems to have an enormous amount
of language-lawyerly discussion that seems somewhat beside the
point. I don't believe that 12.3(13-14) were written with
pragmas in mind, and we should just analyze pragmas on
a case by case basis to determine what make the most sense.
In any case, I believe it was never the intent that just because
a generic library unit had a library unit pragma, then all instances
of the generic must themselves be library units. This seems very
inflexible.
On my own quick perusal, I would recommend that as a *general* rule,
*library* unit pragmas on a generic library unit apply to the
generic *only*, and not automatically to its instances. On the other hand,
program unit pragmas which are *not* library unit pragmas should, by
default, apply to all instances. In both cases, this should just be a
default rule, subject to overriding by rules which are specific to a
particular pragma.
I think these general rules make sense because when talking about
program units inside a generic, there is not much of interest to
say except in terms of instances. On the other hand, library
unit pragmas are often talking about things which relate directly
to library-unit-ness, and relate to "with" clauses, elaboration
order, etc., and might not make sense when applied to particular
instances (which in any case might not be library units).
****************************************************************
!section 08.03(16)
!subject AI-41 and "non-generic equivalents"
!reference AI-00041
!reference RM95-08.03(16)
!from Bob Duff
!reference 96-5479.a Robert A Duff 96-4-12>>
!discussion
Erhard,
I believe you're in charge of AI-41. While you're at it, you might want
to take into account this message I got from Robert Dewar:
> with Ada.Numerics.Generic_Elementary_Functions;
>
> package Ada.Numerics.Elementary_Functions is
> new Ada.Numerics.Generic_Elementary_Functions (Float);
>
> according to our undertanding of the ARG decision, this unit does NOT
> inherit the pragma Pure from the generic package. Therefore it is not
> pure. But surely it is meant to be Pure. We propose adding a Pure
> pragma to this and other similar packages.
I agree with Robert that it is meant to be declared Pure.
The above text does not appear in the RM -- there is no generic
instantiation, but just a statement that
Ada.Numerics.Elementary_Functions is a package that exports certain
functions. A.5.1(9). From that, I think one can argue that it *is*
declared Pure. Anyway, I think it's worth stating in the AI.
There are various other "non-generic equivalents" in the RM that I
suppose should be treated the same way.
- Bob
****************************************************************
Questions? Ask the ACAA Technical Agent