Version 1.3 of ai05s/ai05-0156-1.txt

Unformatted version of ai05s/ai05-0156-1.txt version 1.3
Other versions for file ai05s/ai05-0156-1.txt

!standard 8.6(17)          09-06-25 AI05-0156-1/02
!class ramification 09-06-02
!status WG9 Approved 09-11-05
!status ARG Approved 7-0-0 09-06-13
!status work item 09-06-02
!status received 09-02-13
!priority Low
!difficulty Medium
!qualifier Clarification
!subject Elaborate_All applies to bodies imported with limited with
!summary
Elaborate_All applies to bodies imported (indirectly) via limited with.
!question
Does pragma Elaborate_All apply to bodies of compilation units imported via 'limited with'? (Yes.) For example, is this program legal? (No.)
limited with P2; package P1 is procedure Proc1; end P1; package body P1 is procedure Proc1 is begin null; end; end P1;
with P1; pragma Elaborate_All(P1); package P2 is procedure Proc2; end P2; package body P2 is procedure Proc2 is begin null; end; end P2;
with P1, P2; procedure Main is begin null; end Main;
A strict reading of the Standard shows it to be illegal:
By 10.2.1, every library item that is needed by P1 must be elaborated before P2'Spec.
P1'Spec depends semantically on the limited view of P2'Spec (10.1.1(26/2)).
P1'Spec therefore needs the limited view of P2'Spec (10.2(3-4)).
P1'Spec therefore needs the nonlimited view of P2'Spec (10.2(6.1/2)).
Therefore P2'Spec must be elaborated before P2'Spec, which is a tough constraint to satisfy.
!recommendation
(See Summary.)
!wording
None needed.
!discussion
The "user view" of Elaborate_All is that it ensures that any possible units that could be called are elaborated early enough. That "user view" is surely violated in this case, because there are no possible calls by units that have only a limited view of another unit. In this example, it is not possible for P1 to make a call to P2, so there is no reason for P1 to have an elaboration dependence on P2.
The reason that "needs" includes the non-limited view is to ensure that the non-limited view of P2 is included in the partition whenever P1 is, even if no unit has a semantic dependence on P2.
It appears that the effect of that definition on Elaborate_All was not considered (the author can find no record of such consideration).
However, examples like this are pretty unlikely in practice. The case that inspired the rule is the case of unit tests. A unit test of P1 may not even know or care about P2. But there is no problem with the unit test using Elaborate_All here (both P1 and P2 will be elaborated before the unit test). Since fixing this problem would require introducing a new term similar to but subtly different than "needs" (by excluding the 10.2(6.1/2) bullet), we don't make a fix since it would be much larger than the likelihood of encountering the problem.
!ACATS Test
No new ACATS tests are needed.
!appendix

From: Bob Duff
Date: Friday, February 13, 2009  11:03 AM

Does pragma Elaborate_All apply to bodies of compilation units imported via
'limited with'?  For example, is this program legal?

   limited with P2;
   package P1 is
      procedure Proc1;
   end P1;
   package body P1 is
      procedure Proc1 is begin null; end;
   end P1;

   with P1;
   pragma Elaborate_All(P1);
   package P2 is
      procedure Proc2;
   end P2;
   package body P2 is
      procedure Proc2 is begin null; end;
   end P2;

   with P1, P2;
   procedure Main is
   begin
      null;
   end Main;

Steve Baird's analysis shows it to be illegal:

  By 10.2.1, every library item that is needed by P1 must be
  elaborated before P2'Spec.

  P1'Spec depends semantically on the limited view of P2'Spec
  (10.1.1(26/2)).

  P1'Spec therefore needs the limited view of P2'Spec (10.2(3-4)).

  P1'Spec therefore needs the nonlimited view of P2'Spec (10.2(6.1/2)).

  Therefore P2'Spec must be elaborated before P2'Spec,
  which is tough constraint to satisfy.

Is that the intent?  I find it quite surprising that (1) 'limited with' does
_not_ create a semantic dependence, but _does_ create an elaboration dependence,
and (2) pragma Elaborate_All is almost always illegal when a 'limited with' is
involved.

Steve and Ed Schonberg both say that it doesn't matter, because in practise,
whenever a spec says 'limited with', the body always has a non-limited with.
True?

****************************************************************

From: Ed Schonberg
Date: Friday, February 13, 2009  2:45 PM

> Steve and Ed Schonberg both say that it doesn't matter, because in practise,
> whenever a spec says 'limited with', the body always has a non-limited with. True?

In fact no, and that's why 10.2 (6 1/2) is there:  if the limited view is
mentioned, the non-limited view has to be included in the partition  even if no
one mentions it.   I think there is already an ACATS test  that verifies this.

****************************************************************

From: Tucker Taft
Date: Friday, February 13, 2009  3:10 PM

I agree with Steve.  (I am confused by Ed's reply to your email since he starts
off with "In fact no" but I don't know which of the 4 questions you ask he is
answering.)

A pragma Elaborate_All is illegal if the named unit's body with's the unit with
the Elaborate_All, so it doesn't seem surprising that it is also illegal if the
named unit's spec limited-with's the unit with the Elaborate_All.

I'm not sure why you say an Elaborate_All is almost always illegal when a
limited-with is involved.  It is certainly easy to construct cases where an
Elaborate_All is legal.  It just needs to originate outside the set of units
mentioned in the limited withs.

****************************************************************

From: Randy Brukardt
Date: Friday, February 13, 2009  3:33 PM

> Does pragma Elaborate_All apply to bodies of compilation units
> imported via 'limited with'?

No, of course not. You shouldn't be able to have an elaboration dependence on
something that you don't have a semantic dependence on.

...
> Steve Baird's analysis shows it to be illegal:
>
>   By 10.2.1, every library item that is needed by P1 must be
>   elaborated before P2'Spec.
>
>   P1'Spec depends semantically on the limited view of P2'Spec
>   (10.1.1(26/2)).
>
>   P1'Spec therefore needs the limited view of P2'Spec (10.2(3-4)).
>
>   P1'Spec therefore needs the nonlimited view of P2'Spec
> (10.2(6.1/2)).
>
>   Therefore P2'Spec must be elaborated before P2'Spec,
>   which is tough constraint to satisfy.
>
> Is that the intent?

I don't think so. "Needs" is defined to tell us what is in the partition, not to
define proper elaboration dependence. The two are similar but not identical.

> I find it quite surprising that (1)
> 'limited with' does _not_ create a semantic dependence, but _does_
> create an elaboration dependence, and (2) pragma Elaborate_All is
> almost always illegal when a 'limited with'
> is involved.
>
> Steve and Ed Schonberg both say that it doesn't matter, because in
> practise, whenever a spec says 'limited with', the body always has a
> non-limited with.
> True?

Well, that's definitely not true, as Ed mentions. But if you stuck "almost"
in there, you'd probably be right.

It's clear that in the example Bob gave, Elaborate_All should work. There is no
semantic dependence on P2 in P1, so there cannot be any dependence on the
elaboration of P2. I would have thought that was the definition of elaboration
dependence! (I don't understand Tucker's opinion here at all.) It's also crystal
clear that the current wording is wrong in that sense.

What is not clear is whether it is worth fixing. Most real examples would have a
non-limited with in the body, giving the same net effect whether or not we
changed the wording to allow this case. Perhaps this is a case where it is clear
that the language is broken, but it isn't that important to fix.

Thus I think the appropriate thing to do here is to write a ramification and
confirm the rules as is. (Unless someone can come up with real examples where
this would matter. The ACATS test Ed referred to doesn't count!)

P.S. The ACATS test that Ed referred to is CA20003, with an objective of "Check
that a package that is needed only because it is referenced in a limited with
clause is included in a partition." Here's the scenario I posited where being
consistent about this behavior would be important:

---
A reusable subsystem CA20003_L is developed, including a type Debug_Info and an
operation Display for it. A library package CA20003_0 is created which takes an
access to Debug_Info, but does not display it at this time and defaults it to
null. A main program CA200033 is compiled that tests CA20003_0.

In order to determine which various units are included in the partition, we also
compile a unit CA20003_TC.

In this example, the subsystem accessed by limited with is used only
peripherally in the subsystem being tested. We expect this situation to be
fairly common in unit tests.

Units referenced only by a limited with are nevertheless "needed" by a
partition, as explained in 10.2(6.1/2), and thus are included in the partition.
---

Note that a unit test (such as the main program in this scenario) could use
Elaborate_All successfully. So this case doesn't seem to be an argument for
rewriting the rule, even though it is clearly wrong logically.

****************************************************************

From: Tucker Taft
Date: Friday, February 13, 2009  3:43 PM

>> Does pragma Elaborate_All apply to bodies of compilation units
>> imported via 'limited with'?
>
> No, of course not. You shouldn't be able to have an elaboration
> dependence on something that you don't have a semantic dependence on.
 > ...

I'm confused by this.  It is quite common to have an elaboration dependence on
something where you don't have a semantic dependence.  A pragma Elaborate, for
example, creates an elaboration dependence on a body without creating a semantic
dependence on it.  And the case of interest here is that Elaborate_All creates
an elaboration dependence on everything needed by the named unit, but doesn't
create any semantic dependences.

It is the converse statement that makes more sense, namely, you can't have a
semantic dependence without also having an elaboration dependence.  Hence, if
you "with" something, or are a child of something, then you have a semantic
dependence on the spec of "something."  And you get an elaboration dependence as
well, of course.

I didn't study the rest of Randy's reply because I was confused from the get-go.

****************************************************************

From: Randy Brukardt
Date: Friday, February 13, 2009  4:20 PM

> I'm confused by this.  It is quite common to have an elaboration
> dependence on something where you don't have a semantic dependence.  A
> pragma Elaborate, for example, creates an elaboration dependence on a
> body without creating a semantic dependence on it.  And the case of
> interest here is that Elaborate_All creates an elaboration dependence
> on everything needed by the named unit, but doesn't create any
> semantic dependences.

OK, sorry, I was thinking of semantic dependence as something that applies to an
entire package (spec and body), not just a compilation unit.

It surely is true (or ought to be true) that you can't have an (direct)
elaboration dependence on a body if you don't have a semantic dependence on the
spec. Because in that case, you can't call or use anything in the package, so
whether or not it is elaborated is irrelevant. (You might get an indirect
elaboration dependence via another unit which has a semantic dependence.) But I
fail to see why we should have an elaboration dependence on a unit that has no
semantic dependence on any other unit.

> It is the converse statement that makes more sense, namely, you can't
> have a semantic dependence without also having an elaboration
> dependence.  Hence, if you "with"
> something, or are a child of something, then you have a semantic
> dependence on the spec of "something."  And you get an elaboration
> dependence as well, of course.

Well, elaboration dependence is mainly about bodies, and semantic dependence is
about specs. Trying to tie one to the other is unlikely to work out well.

But that's irrelevant to the point at hand.

> I didn't study the rest of Randy's reply because I was confused from
> the get-go.

You should have read the rest, because it concluded that fixing the problem
wasn't worthwhile. (Which you should be able to agree with even if you think
there isn't a problem. :-) At least until someone comes up with a realistic
example of why it could matter.

But I was (and still am) confused by your reply. I'd like to know why you think
that Bob's example should have an elaboration dependence on P2 from P1, when P1
can't even call anything in P2, declare an object of a type declared in P2, etc.
How could P1 depend on the elaboration of P2 such that it could fail? (I'm not
arguing that it does have an elaboration dependence based on the current
wording, I'm just wondering why it should.)

****************************************************************

From: Robert Dewar
Date: Friday, February 13, 2009  4:31 PM

> But I was (and still am) confused by your reply. I'd like to know why
> you think that Bob's example (see below) should have an elaboration
> dependence on P2 from P1, when P1 can't even call anything in P2,
> declare an object of a type declared in P2, etc. How could P1 depend
> on the elaboration of P2 such that it could fail? (I'm not arguing
> that it does have an elaboration dependence based on the current
> wording, I'm just wondering why it should.)

Seems clear to me that it shouldn't!

****************************************************************

From: Bob Duff
Date: Friday, February 13, 2009  4:29 PM

> I don't think so. "Needs" is defined to tell us what is in the
> partition, not to define proper elaboration dependence. The two are
> similar but not identical.

They were identical in Ada 95 (i.e. before 'limited with' was invented).
Tuck, Steve, and (perhaps?) Ed think they are _still_ identical.

> What is not clear is whether it is worth fixing.

I suppose I can live with not fixing it.
Anyway, I'm at least half convinced by Tucker's arguments.

For what it's worth, GNAT does not complain about the example in my original
message.  This is true whether or not you use the non-standard "static"
elaboration model, or the standard Ada model.

> P.S. The ACATS test that Ed referred to is CA20003, with an objective
> of "Check that a package that is needed only because it is referenced
> in a limited with clause is included in a partition." Here's the
> scenario I posited where being consistent about this behavior would be important:
>
> ---
> A reusable subsystem CA20003_L is developed, including a type
...
> ---

I am puzzled by the above.  Are you intending to explain why 10.2(6.1/2)
requires compilation units to be included in the partition, even when they're
only reachable via 'limited with'?

****************************************************************

From: Randy Brukardt
Date: Friday, February 13, 2009  5:01 PM

I was intending to explain why I was testing this objective. I struggled for a
long time with this particular objective, as I wondered whether any case of it
were pathological. I suspected that this test would break GNAT (which it did,
since fixed), and I didn't want to be making work for implementers unless there
was a reasonable chance that it would matter to a real program. Eventually I
came up with the "unit test" scenario that I gave above, which seemed realistic
enough that I created the test that way. (Keep in mind that ACATS C-Tests are
supposed to reflect real usage scenarios, so I needed to find one to justify the
C-Test.)

I went and looked this up now to see if this scenario (I couldn't remember what
it was) would provide a reason that we should go through the effort of rewriting
the rules for Elaborate_All. But it does not.

****************************************************************

From: Tucker Taft
Date: Friday, February 13, 2009  5:03 PM

> It surely is true (or ought to be true) that you can't have an
> (direct) elaboration dependence on a body if you don't have a semantic
> dependence on the spec.

I may still not understand what you mean by "semantic" dependence. It sounds
like you are including all with clauses that appear anywhere within the unit's
spec or body, and following them all transitively.

In the reference manual, "semantic dependence" is a relationship between
compilation units, not library units.  So if you use the term in some other way,
it would help if you qualified it somehow, or you will keep confusing at least
me.  Perhaps you should sneak in the word "closure," i.e. there is no point in
one unit having an elaboration dependence on a second unit if that second unit
is not in the semantic "closure" of the first unit.

> ...
> But I was (and still am) confused by your reply. I'd like to know why
> you think that Bob's example (see below) should have an elaboration
> dependence on P2 from P1, when P1 can't even call anything in P2,
> declare an object of a type declared in P2, etc. How could P1 depend
> on the elaboration of P2 such that it could fail? (I'm not arguing
> that it does have an elaboration dependence based on the current
> wording, I'm just wondering why it should.)

I wasn't arguing rationale, I was arguing about what we said in the manual,
intentionally, I believe.  We said that "limited with" creates a "need"
relationship, knowing we already used the "need" relationship in the definition
of the effect of Elaborate_All.

If you (and perhaps Bob) are arguing that we should invent a different
relationship for Elaborate_All, I can understand that, but I think I agree with
Randy that it isn't worth the trouble.

The effect of the Elaboration pragmas is already very confusing to most Ada
users (including me with my user hat on!), and adding a new relationship that is
subtly different from "need" seems like adding gratuitous complexity (which I
usually love ;-).

****************************************************************

From: Robert Dewar
Date: Friday, February 13, 2009  5:12 PM

> The effect of the Elaboration pragmas is already very confusing to
> most Ada users (including me with my user hat on!), and adding a new
> relationship that is subtly different from "need" seems like adding
> gratuitous complexity (which I usually love ;-).

That's a language lawyer viewpoint!

Elaborate_All has a perfectly well understood meaning from a programmers usage
point of view, it ensures that any possible units that could be called are
elaborated early enough.

If the description in the RM does not correspond to this basic pragmatic
definition, then it is the description that is confusing.

This example is a case where it would be really hard to explain to a programmer
why the program is illegal, because you can't do it in the appropriate terms of
pragma Elaborate_All fundamental intention, instead you have to refer to (to
most programmers) meaningless rubbish in the RM to justify a clearly peculiar
outcome.

I certainly don't think GNAT will bother to fix this case! And I doubt Randy can
justify adding a test :-)

****************************************************************

From: Randy Brukardt
Date: Friday, February 13, 2009  5:25 PM

> I wasn't arguing rationale, I was arguing about what we said in the
> manual, intentionally, I believe.  We said that "limited with" creates
> a "need" relationship, knowing we already used the "need" relationship
> in the definition of the effect of Elaborate_All.

I agree with you up to the point of "intentionally". The only thing I recall
being discussed was that "need" was the way to ensure that a unit was part of
the partition. If we discussed the effect on elaboration, I don't remember it.
(It surely was a surprise to me today to find out that Elaborate_All depends on
"need"; I surely didn't remember that.)

> If you (and perhaps Bob) are arguing that we should invent a different
> relationship for Elaborate_All, I can understand that, but I think I
> agree with Randy that it isn't worth the trouble.

If we were going to do this right, there surely ought to be a different
relationship. But it's not clear that it really would matter in practice, so I
don't know that I want to spend the time it would take to craft the proper
relationship.

> The effect of the Elaboration pragmas is already very confusing to
> most Ada users (including me with my user hat on!), and adding a new
> relationship that is subtly different from "need" seems like adding
> gratuitous complexity (which I usually love ;-).

Then I'm surprised that you haven't written piles of praise for my various
accessibility trial balloons. :-)

****************************************************************

From: Randy Brukardt
Date: Friday, February 13, 2009  5:29 PM

...
> I certainly don't think GNAT will bother to fix this case!
> And I doubt Randy can justify adding a test :-)

I don't think it will be in my top 100, that's for sure.

Seriously, if we could find a case sufficiently likely to justify adding a test,
then I think we also have a justification for the work needed to change the rule
to make sense. It's the fact that I can't find any such case that leads me to
suggest not fixing it.

****************************************************************

From: Robert Dewar
Date: Friday, February 13, 2009  5:35 PM

I agree, so far this is definitely in the pathology category

****************************************************************

Questions? Ask the ACAA Technical Agent