Version 1.7 of ai12s/ai12-0070-1.txt

Unformatted version of ai12s/ai12-0070-1.txt version 1.7
Other versions for file ai12s/ai12-0070-1.txt

!standard 3.10.2(13.1/3)          13-10-07 AI12-0070-1/03
!standard 9.3(2)
!class binding interpretation 13-05-30
!status Corrigendum 2015 13-07-15
!status WG9 Approved 13-11-15
!status ARG Approved 6-0-3 13-06-15
!status work item 13-05-30
!status received 13-05-02
!priority Low
!difficulty Easy
!qualifier Error
!subject 9.3(2) does not work for anonymous access types
!summary
The master of an anonymous access type is defined in 7.6.1 (often via 3.10.2), and a task created by an allocator for an anonymous access type has that master, regardless of whatever 9.3 says.
!question
9.3(2) says:
If the task is created by the evaluation of an allocator for a given access type, it depends on each master that includes the elaboration of the declaration of the ultimate ancestor of the given access type.
This rule hasn't changed since the original Ada 95. This rule was written when all access types were named, and it works fine when an allocator type is a named access type. But if the type of an allocator is an anonymous access type, this rule doesn't make any sense. Anonymous access types don't have declarations of their own; they are part of some larger declaration. Moreover, we have lots of rules that specify what the accessibility (and thus the master) of an anonymous access type is. This rule overrides all of that, and would cause bizarre effects for access results, stand-alone objects of an anonymous acceess type, and access discriminants. Is this intended? (Surely not.)
!recommendation
(See !summary.)
!wording
Modify 9.3(2):
If the task is created by the evaluation of an allocator for a given {named} access type, it depends on each master that includes the elaboration of the declaration of the ultimate ancestor of the given access type.
---
Vaguely related fix:
Mark the last sentence of 6.5(5.3/2) redundant.
Add after 3.10.2(13.1/3): [This is immediately before the definition for a SAOAAT.]
The accessibility level of the anonymous access subtype defined by a return_subtype_indication that is an access_definition (see 6.5) is that of the result subtype of the enclosing function.
!discussion
3.10.2(14/3) and its many related paragraphs clearly define the accessibility level of an object declared by an allocator; and each accessibility level has an associated master. It's clearly the intent that these (complex) rules apply to tasks as well as finalization; there were many examples of task termination discussed during the crafting of these rules.
So 9.3(2) must at least refer to those rules and not try to invent its own.
We chose the most minimum possible fix, just changing the existing bullet to only apply to named access types. This depends on the fact that 9.2(3.1/2) is sufficient to describe the behavior for ALL cases; as such, we use it to describe the behavior for all but the most basic cases.
This also fixes a related problem. A stand-alone object of an anonymous access type (SAOAAT) is an object_declaration. So for something like:
A : access A_Task_Type := new A_Task_Type;
both the original 9.3(2) and 9.3(3) apply! With the fix, 9.3(2) clearly no longer applies.
A vaguely related point:
The questioner also notes that 6.5(5.3) is the only rule that defines the accessibility of something that is not in 3.10.2. Thus, a copy of it is added to 3.10.2 for completeness, and the original was marked redundant.
!corrigendum 3.10.2(13.1/3)
Insert after the paragraph:
the new paragraphs:
!corrigendum 9.3(2)
Replace the paragraph:
by:
!ACATS Test
No extra ACATS test is needed (presumably, tests for other objectives try such cases, although that might be optimistic).
!ASIS
No ASIS effect.
!appendix

!topic 9.3(2) is broken with respect to anonymous access types
!reference 9.3(2)
!from Adam Beneschan 13-05-02
!discussion

This arose out of a recent discussion on comp.lang.ada
(https://groups.google.com/forum/?hl=en&fromgroups=#!topic/comp.lang.ada/NE-vR1pvgSo).

9.3(2) says:

    If the task is created by the evaluation of an allocator for a
    given access type, it depends on each master that includes the
    elaboration of the declaration of the ultimate ancestor of the
    given access type.

This rule hasn't changed since the original Ada 95, and it's
essentially the same as the rule in RM83 9.4(2), with "ultimate
ancestor" added:

    The task designated by a task object that is the object, or a
    subcomponent of the object, created by the evaluation of an
    allocator depends on the master that elaborates the corresponding
    access type definition.

This rule was written when all access types were named, and I believe
it works fine when an allocator type is a named access type.  But if
the type of an allocator is an anonymous access type, it's not clear
how this rule is supposed to apply.  First of all, I don't think
anonymous access types have "declarations":

    3.1(5): A declaration is a language construct that associates a
    name with (a view of) an entity.

and this can't apply to anonymous access types since there's no name
to associate.  I can't find anywhere in 3.10 where it defines what the
"declaration" of an anonymous access type would be.  But even if we
were to assume that the "declaration" is a larger declaration that
contains an access_definition, such as the declaration of a function
that returns an anonymous access type, it appears that the results are
not what people expect.

    task type T1 is ...

    function Return_Acc_T1 (N : Integer) return access T1 is
    begin
        return T : access T1 do
            T := new T1;     -- (A)
        end return;
    end Return_Acc_T1;

    procedure P ...
    begin
        ...
        declare
            A1 : array (1 .. 2) of access T1 :=
                    (Return_Acc_T1(1), Return_Acc_T1(2));
        begin
            ...
        end;
    end P;

When the tasks of type T1 are allocated at (A), what master do they
depend on?  9.3(2) says the answer depends on who elaborates the
*declaration* of the "given access type".  What's the "given access
type"?  And which declaration does it use?  The one in the function
declaration, the one in the extended return declaration, or the one in
the declaration of array A1?  Randy thought the tasks' master is the
block that declares A1, based on new rules in 3.10.2(10.2ff) that
change what the "master of a function call" is.  But I don't think
there's any language in 9.3(2) that makes it clear that the master of
a function call is relevant.

I believe 9.3(2) needs to be fixed, perhaps by adding "named" to it:

    If the task is created by the evaluation of an allocator for a
    given {named} access type, it depends on each master that includes
    the elaboration of the declaration of the ultimate ancestor of the
    given access type.

and adding another paragraph after:

    If the task is created by the evaluation of an allocator for a
    given anonymous access type, then:
    (a) if the anonymous access type is a function result type, or the
        return_subtype_indication of an extended_return_statement that
        applies to a function with an anonymous access result type,
        then the task depends on the master of the function call (and
        on each enclosing master ... ???)
    (b) in other cases ... ???  (sorry, I don't know what would be
        intended)

I'm afraid that a new rule would be pretty complicated, and
unfortunately probably not provide much benefit.  But it seems to me
that 9.3(2) just doesn't work in this case, and something needs to be
done.  If the answer is just to disallow this--to add a rule to 4.8
that if an allocator's type is anonymous access, its designated type
may not have a task subcomponent--that wouldn't upset me too much.
That would force a programmer to make it clear (by using a named
access type) who is supposed to be the task's master, which is
probably a good thing.

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

From: Randy Brukardt
Sent: Thursday, May  2, 2013  5:30 PM

...
> 9.3(2) says:
>
>     If the task is created by the evaluation of an allocator for a
>     given access type, it depends on each master that includes the
>     elaboration of the declaration of the ultimate ancestor of the
>     given access type.
>
> This rule hasn't changed since the original Ada 95,
...
> But if the type of an allocator is an anonymous access type, it's not
> clear how this rule is supposed to apply.

Here, the Dewar rule clearly applies: the standard does not say anything silly,
even if the literal language does.

Everyone "knows" that the model is that an allocated task belongs to the master
of the access type. (Let me be clear that I don't think the literal wording
"master of the access type" is defined, but something similar to it is. Trips
into the "Heart of Darkness" are not for the faint of heart, and I'm not ready
to do that right now.)

We have several *pages* of rules that define what the master of an access type
is, in 7.6.1 and 3.10.2 (you need both to understand it - 3.10.2 defines the
"accessibility level" of entities, and there is a rule somewhere that says that
the masters follow the same rule).

9.3(2) should simply say something about depending on the master of the access
type. Copying all of the rules in 3.10.2 and 7.6.1 is madness. (The current
wording says "each master", for instance.)

It would be best of all if task waiting was defined in terms of finalization;
then all of the cruft could be swept away. ("The first step of finalizing a
master is waiting for any tasks associated with that master."). Indeed, 9.3(5)
already says this, so I really don't know why 9.3(2, 3, 3.1) says "each master".
The only one that matters is the one that will do the waiting, the others have
no effect so why talk about them?

9.3(3.1/2) really defines the intended semantics, for all tasks. Not quite sure
why we need the other bullets. (A task is an object, whether allocated by a
allocator, a stand-alone object declaration, or as a component/return
statement/whatever.)

So I'd strongly suggest deleting 9.3(2-3), merging 9.3(1) and 9.3(3.1/2) into a
single paragraph. And possibly creating a note that says something like the
bullets 9.3(2-3).

Of course, the trivial fix would be to just add "named" to 9.3(2) as you
suggested, and let anonymous access types fall into the "otherwise" bullet
(9.3(3.1/2)). But I don't see much value to the existing bullets (other than to
keep me employed by contradicting the rest of the standard :-).

Now, you also could be arguing that the master of some anonymous access type is
not well-defined (as you know, there are several kinds with completely different
rules for masters, so bugs are likely). That's possible in some case, but please
explain that in detail if you think so.

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

From: Bob Duff
Sent: Thursday, May  2, 2013  6:11 PM

> It would be best of all if task waiting was defined in terms of
> finalization; then all of the cruft could be swept away. ("The first
> step of finalizing a master is waiting for any tasks associated with that master.").
> Indeed, 9.3(5) already says this, so I really don't know why 9.3(2, 3,
> 3.1) says "each master". The only one that matters is the one that
> will do the waiting, the others have no effect so why talk about them?

IIRC, the "each master" wording dates back to Ada 83, and it was necessary then
(and still is) because you can have a block statement in task body Outer, and
the block statement is the master of some inner tasks, and the block statement
has a select-with-terminate for Outer.  So Outer can be ready to terminate (i.e.
waiting on an open terminate alternative) while it has dependent tasks at
several nesting levels.

A whole tree of tasks can vanish when some sub-sub-sub task terminates or
reaches a terminate alt.

I don't know how all this interacts with anonymous access types (which is not my
favorite feature of Ada!), but I'd be wary of meddling with this wording too
much.

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

From: Adam Beneschan
Sent: Thursday, May  2, 2013  6:30 PM

> Now, you also could be arguing that the master of some anonymous
> access type is not well-defined (as you know, there are several kinds
> with completely different rules for masters, so bugs are likely).
> That's possible in some case, but please explain that in detail if you think
> so.

No, I'm not arguing anything that subtle.  In truth, I haven't been able to keep
up with the changes in the accessibility level rules and their ramifications.

By the way, I noticed that all accessibility levels for all entities seem to be
defined in 3.10.2, with one exception: 6.5(5.3), which defines the accessibility
of anonymous access types in extended returns.  I had trouble finding this at
first.  Maybe the ARG should consider putting a copy of this rule in 3.10.2, so
that they're all in one place.  (Based on that rule, and presuming that the
interpretation you've described is the intended one, it looks like the behavior
in the original comp.lang.ada example is a compiler bug.)

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

From: Randy Brukardt
Sent: Thursday, May  2, 2013  6:34 PM

> A whole tree of tasks can vanish when some sub-sub-sub task terminates
> or reaches a terminate alt.

OK, that makes sense (sort of).

> I don't know how all this interacts with anonymous access types (which
> is not my favorite feature of Ada!), but I'd be wary of meddling with
> this wording too much.

I think that 9.3(3.1/3) is actually adequate for describing the master(s) of any
possible Ada task. Do you agree?

The reason I ask is that there are so many weird cases that we've added in Ada
2005 and Ada 2012 that fixing up this wording seems like more trouble than it's
worth. Let's just use the rules for masters declared elsewhere and not have
not-quite-right rules in other places mucking up the works.

In addition to Adam's original question, I was wondering if a SAOAAT
(stand-alone object of an anonymous access type) gets the right master as it
seems that *both* original bullets might apply.

So the less said here, the better. It's tough enough to get the rules right in
3.10.2 and 7.6.1 without having a copy somewhere else.

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

From: Randy Brukardt
Sent: Thursday, May  2, 2013  6:39 PM

> > Now, you also could be arguing that the master of some anonymous
> > access type is not well-defined (as you know, there are several
> > kinds with completely different rules for masters, so bugs are likely).
> > That's possible in some case, but please explain that in detail if
> > you think so.
>
> No, I'm not arguing anything that subtle.  In truth, I haven't been
> able to keep up with the changes in the accessibility level rules and
> their ramifications.

Neither has anyone else. :-) I expect this area to be a continuing source of
merriment for years to come. :-)

> By the way, I noticed that all accessibility levels for all entities
> seem to be defined in 3.10.2, with one exception: 6.5(5.3), which
> defines the accessibility of anonymous access types in extended
> returns.  I had trouble
> finding this at first.  Maybe the ARG should consider putting a copy
> of this rule in 3.10.2, so that they're all in one place.

Are you sure that it's the *only one*? If so, I agree with you, but if there are
others, the case is weakened considerably.

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

From: Adam Beneschan
Sent: Thursday, May  2, 2013  6:49 PM

> Are you sure that it's the *only one*? If so, I agree with you, but if
> there are others, the case is weakened considerably.

I think so.  I searched a text version of AARM12 for the phrase "accessibility
level" and looked for places where it might be defined.  On the other hand, the
file I searched is about a year out of date, so I should probably try the same
thing with the most recent version.

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

From: Adam Beneschan
Sent: Thursday, May  2, 2013  7:05 PM

> IIRC, the "each master" wording dates back to Ada 83, and it was
> necessary then (and still is) because you can have a block statement
> in task body Outer, and the block statement is the master of some
> inner tasks, and the block statement has a select-with-terminate for
> Outer.  So Outer can be ready to terminate (i.e. waiting on an open
> terminate alternative) while it has dependent tasks at several nesting
> levels.

I don't see the phrase "each master" in RM83 9.4(2), but RM83 does say
this:

"Furthermore, if a task depends on a given master that is in a block statement
executed by another master, then the task depends also on this other master, in
an indirect manner ..."

and it goes on for a while.  I'm guessing changing this to "each master that
includes..." was a nicer way to say the same thing.  But I think you're right
that the RM does need to make it clear that a master's dependent tasks include
tasks in a sub-sub-sub-master or whatever.

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

From: Jean-Pierre Rosen
Sent: Friday, May  3, 2013  2:40 AM

> IIRC, the "each master" wording dates back to Ada 83, and it was
> necessary then (and still is) because you can have a block statement
> in task body Outer, and the block statement is the master of some
> inner tasks, and the block statement has a select-with-terminate for
> Outer.  So Outer can be ready to terminate (i.e. waiting on an open
> terminate alternative) while it has dependent tasks at several nesting levels.

Right, I remember I was puzzled by this, until I implemented the termination
algorithm in Ada/ED, and discovered that it was necessary. Don't remember the
details though, it was a loooong time ago. (If anyone is interested, I could
investigate into my PhD thesis, if the dust that covers it is not too thick).

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


Questions? Ask the ACAA Technical Agent