Version 1.2 of ai05s/ai05-0224-1.txt
!standard A.4.7(28) 10-10-21 AI05-0224-1/00
!standard A.4.8(28/2)
!class binding interpretation 10-10-21
!status work item 10-10-21
!status received 10-06-07
!priority Low
!difficulty Medium
!qualifier Error
!subject No_Task_Allocators and classwide returns
!summary
!question
How does the No_Task_Allocators restriction interact with a function that
returns Some_Limited_Type'Class, as in
type Ref is access Some_Limited_Type'Class;
type T is new Some_Limited_Type with
record Tsk : Some_Task_Type; end record;
function F return Some_Limited_Type'Class is
begin return X : T; end F;
Ptr : Ref := new Some_Limited_Type'Class'(F);
!wording
!discussion
!ACATS Test
!appendix
From: Steve Baird
Sent: Monday, June 7, 2010 2:20 PM
How does the No_Task_Allocators restriction interact with a function that
returns Some_Limited_Type'Class, as in
type Ref is access Some_Limited_Type'Class;
type T is new Some_Limited_Type with
record Tsk : Some_Task_Type; end record;
function F return Some_Limited_Type'Class is
begin return X : T; end F;
Ptr : Ref := new Some_Limited_Type'Class'(F);
Does this restriction need a dynamic rule to deal with the cases like this?
****************************************************************
From: Randy Brukardt
Sent: Monday, June 7, 2010 2:34 PM
I don't think it *has* to have a dynamic rule, since this clearly (!) can be
checked at link-time, and restrictions are technically post-compilation checks
anyway.
The better question in my view is whether we intend implementations to do the
link-time handstands this requires (and if so, why). (You need to do the check
at link-time as the body of F probably is separately compiled from the
allocator, and you need to know about both in order to show a problem.)
****************************************************************
From: Gary Dismukes
Sent: Monday, June 7, 2010 3:13 PM
> I don't think it *has* to have a dynamic rule, since this clearly (!)
> can be checked at link-time, and restrictions are technically
> post-compilation checks anyway.
But there are cases that might not be checkable at link time, such as when the
function has multiple returns, only some of which have task parts.
****************************************************************
From: Randy Brukardt
Sent: Monday, June 7, 2010 3:30 PM
> But there are cases that might not be checkable at link time, such as
> when the function has multiple returns, only some of which have task
> parts.
I don't think that people who want to enforce this particular restriction (which
is intended to simplify the runtime system) care whether there is *actually* a
task allocator; I think they only care that there *might be* a task allocator.
After all, you could put if False then around the allocator itself -- but that
would still violate the restriction. So it makes sense to me that any
possibility of returning a task from the function would be flagged if the
function is subsequently used in an allocator.
Specifically, I don't see much difference between:
if False then
Ptr := new Some_Type_Containing_a_Task;
end if;
and
Ptr := new Root'Class (F);
function F return Root'Class is
begin
if False then
return Obj:T;
else
return Obj2:S;
end if;
end F;
(where type T has a task and type S does not).
And the point that I recalled above (that the restriction is intended to
simplify the runtime system) implies that a runtime check is inappropriate.
A more interesting question is what do implementations currently do in this
case? We ought to follow practice if there is in fact any to follow.
****************************************************************
From: Steve Baird
Sent: Monday, June 7, 2010 3:34 PM
> But there are cases that might not be checkable at link time, such as
> when the function has multiple returns, only some of which have task parts.
Right. Other cases include dispatching calls and calls through
access-to-function values. This is not, in general, checkable at link time.
****************************************************************
From: Steve Baird
Sent: Monday, June 7, 2010 3:39 PM
I think that if you want to check this restriction completely without runtime
checks, then you would have to be conservative and reject some allocators (e.g.,
the one in my example) on the grounds that the type of the allocated object
*might* have a task part.
****************************************************************
From: Randy Brukardt
Sent: Monday, June 7, 2010 6:51 PM
Right. The current check is conservative anyway: there is no guarantee that the
allocator of a task will be executed, but the program is rejected simply by its
existence. The only question I would have is "how conservative"? I would think
that banning allocators of all limited class-wide types would be going too far,
so some sort of post-compilation check would be needed. Perhaps simply banning
allocators of a limited class-wide type where any extension has a task component
would be adequate (that would be somewhat easier to implement than trying to
figure out for every function whether it could return a task). In any case, I
think we'll need some additional wording for this rule (whatever we decide).
****************************************************************
From: Steve Baird
Sent: Thursday, October 21, 2010 4:47 PM
Before trying to come up with wording for this recently-created AI, I need to
know what rule we want to express.
!question
How does the No_Task_Allocators restriction interact with a function that
returns Some_Limited_Type'Class, as in
type Ref is access Some_Limited_Type'Class;
type T is new Some_Limited_Type with
record Tsk : Some_Task_Type; end record;
function F return Some_Limited_Type'Class is
begin return X : T; end F;
Ptr : Ref := new Some_Limited_Type'Class'(F);
Possible solutions include:
1) If the restriction is given, then conservatively
reject all access-to-limited-classwide
allocators on the grounds that they
might violate the restriction.
2) A post-compilation check that
if the restriction is given and an
allocator exists which allocates an object of type
Some_Limited_Type'Class, then there exist
no extensions of Some_Limited_Type which
have task subcomponents. Or something like that.
3) A runtime check that raises Program_Error if the
restriction is in force and the program
attempts to allocate a task (via some mechanism
such as the given example which makes it past the
static checks).
I'd like to get a consensus on what we want here so that I can try to have
wording for it before the Fairfax meeting.
Opinions?
P.S. My preference order is #2, #1, #3.
****************************************************************
From: Bob Duff
Sent: Thursday, October 21, 2010 5:13 PM
> Before trying to come up with wording for this recently-created AI,
It seems to be so recent that it's in the future.
That is, I don't see it on the ada-auth web site.
And I've never heard of it.
So I'm kind of flying blind here, but...
> P.S. My preference order is #2, #1, #3.
Hmm. I think #3 is best.
#1 is no good -- why should limited types be punished just because they MIGHT
contain tasks?
#2 is a big pain for implementers, for little gain.
****************************************************************
From: Steve Baird
Sent: Thursday, October 21, 2010 5:25 PM
>> Before trying to come up with wording for this recently-created AI,
>
> It seems to be so recent that it's in the future.
> That is, I don't see it on the ada-auth web site.
> And I've never heard of it.
>
Yeah, this one just landed in my lap today, but if you've seen the !question section, then you've seen the whole AI at this point.
> So I'm kind of flying blind here, but...
>
>> P.S. My preference order is #2, #1, #3.
>
> Hmm. I think #3 is best.
Thanks for taking the time to reply.
I don't feel strongly about it, but my idea was that implementors of a runtime
system which is built for use with this restriction don't want to deal with this
issue at all. They want to know statically that task allocation can't happen.
****************************************************************
From: Bob Duff
Sent: Thursday, October 21, 2010 5:40 PM
> Thanks for taking the time to reply.
You're welcome.
> I don't feel strongly about it, but my idea was that implementors of a
> runtime system which is built for use with this restriction don't want
> to deal with this issue at all. They want to know statically that task
> allocation can't happen.
Yes, I agree with that. But replacing every "create some tasks"
with "raise.." seems easy, and accomplishes that goal, while all kinds of
link-time checks seems hard.
****************************************************************
From: Randy Brukardt
Sent: Thursday, October 21, 2010 5:58 PM
...
> > Before trying to come up with wording for this recently-created AI,
>
> It seems to be so recent that it's in the future.
> That is, I don't see it on the ada-auth web site.
> And I've never heard of it.
It was created out of mail from this list on June 7th. So you *ought* to have
heard of it (but you didn't comment on it at the time).
****************************************************************
From: Randy Brukardt
Sent: Thursday, October 21, 2010 6:06 PM
...
> > I don't feel strongly about it, but my idea was that implementors of
> > a runtime system which is built for use with this restriction don't
> > want to deal with this issue at all. They want to know statically
> > that task allocation can't happen.
>
> Yes, I agree with that. But replacing every "create some tasks"
> with "raise.." seems easy, and accomplishes that goal, while all kinds
> of link-time checks seems hard.
Humm. I guess I don't see this, as it seems unlikely to me that the check could
be performed outside of the task supervisor. So quite a bit of the overhead of
creating tasks would be present in the generated code, even if it wasn't used.
That's not the point.
Specifically, I don't see how the function F in Steve's example could be
compiled without the overhead of being able to create tasks, because there is no
way for it to know whether it is called from an allocator (which would raise an
exception) or from an object initialization (which would work - at least in the
absence of other restrictions). And that means that the call site would need at
least some of the overhead of task creation in order to be able to meet the
calling convention of the function (since it couldn't know if a task was
actually created, and no exception could be raised if it was not).
Indeed, that seems to be a problem for *any* version of this restriction other
than the over-the-top #1.
Not sure what to do here...
****************************************************************
Questions? Ask the ACAA Technical Agent