Version 1.3 of ai05s/ai05-0103-1.txt
!standard 6.5(5.2/2) 08-08-14 AI05-0103-1/03
!class binding interpretation 08-06-15
!status work item 08-06-15
!status received 06-04-25
!priority Low
!difficulty Medium
!qualifier Omission
!subject Return statements should require at least static compatibility
!summary
The subtype_indication in an extended_return_statement must be statically
compatible with the result subtype of the function, and for elementary
types, must statically match the result type.
!question
We use static matching to require that null exclusions match on a function
and any extended return:
type An_Access is access Integer;
function Nice return not null An_Access is
begin
return Obj : An_Access do --
Obj := null;
end return;
end Nice;
This is because 6.5(5.2/2) requires static matching for the
subtype_indication and the result subtype if the result subtype is
constrained. An_Access is constrained as defined by 3.10(14/1).
But consider the following small change to An_Access:
type An_Access is access String;
function Nice return not null An_Access is
begin
return Obj : An_Access do --
Obj := null;
end return;
end Nice;
Now An_Access is not constrained as defined by 3.10(14/1) [the designated
subtype is an unconstrained array]. Thus the first part of 6.5(5.2/2) does
not apply, and no matching is required. So it appears that we've succeeded
in returning null from a null-excluding function. Ouch.
!wording
Modify 6.5(5.2) (as previous modified by AI05-0032-1):
If the result subtype of the function is defined by a subtype_mark, the
return_subtype_indication shall be a subtype_indication. The type of the
subtype_indication shall be covered by the result type of the function.
[If the result subtype of the function is constrained, then the]{The} subtype
defined by the subtype_indication shall [also ]be {statically compatible
with the result subtype of the function; if the result type of the function
is elementary, the two subtypes }[constrained and ]shall statically
match[ this result subtype]. If the result subtype of the function is
[unconstrained]{indefinite}, then the subtype defined
by the subtype_indication shall be a definite subtype, or there shall be an
expression.
!discussion
This new wording correctly handles the cases involving null exclusions
because these are handled correctly in the definition of static compatibility.
The new wording does not need to talk about "constrained" and "unconstrained"
as that is included in the definition of static compatibility.
The existing stricter checking for elementary types is preserved; this
disallows the following (arguably reasonable) example:
function F1 return Integer is
begin
return X : Natural do --
...;
end return;
end F1;
Recall that static compatibility of constrained scalar types does not
imply static matching as it does for other constrained types.
There would be no definitional problems associated with omitting
"; if the result type of the function is elementary, then
the two subtypes shall statically match"
from the wording above, but there does not seem to be adequate
justification for changing the language to allow cases such
as the preceding example.
[Editor's note: This also makes access constraints illegal. For example:
function F2 return Acc_String is
begin
return X : Acc_String(1..10) do --
...
end return;
end F2;
Unlike composite types, this constraint is not needed nor used to determine
the shape of the designated object. That comes from the allocator that created
it (or, in the case of 'Access, the aliased object itself). So no capability
is lost by this restriction. The extra checks that would be needed to
implement this constraint buy little, especially as they are not required
by the specification of the function.]
Is "static compatibility" well defined in the case where the the
type of the first subtype is covered by, but is not the same as,
the type of the second subtype? Pending the resolution of AI05-0057, all
we really depend on is a rule that if T is the first named subtype of a
specific tagged type, then any subtype of any type that is covered by T
is statically compatible with T'Class. If that is not the case (e.g.,
if it were determined that static compatibility is only defined for two
subtypes of the same type), then further wording changes are needed.
--!corrigendum 6.5(5.2/2)
!ACATS Test
!appendix
From: Randy Brukardt
Sent: Friday, April 25, 2008 12:06 AM
Here's another one that will remind you that I'm working on ACATS tests...
We use static matching to require that null exclusions match on a function
and any extended return:
type An_Access is access Integer;
function Nice return not null An_Access is
begin
return Obj : An_Access do -- ERROR:
Obj := null;
end return;
end Nice;
This is because 6.5(5.2/2) requires static matching for the
subtype_indication and the result subtype if the result subtype is
constrained. An_Access is constrained as defined by 3.10(14/1).
But consider the following small change to An_Access:
type An_Access is access String;
function Nice return not null An_Access is
begin
return Obj : An_Access do -- OK!!
Obj := null;
end return;
end Nice;
Now An_Access is not constrained as defined by 3.10(14/1) [the designated
subtype is an unconstrained array]. Thus the first part of 6.5(5.2/2) does
not apply, and no matching is required. So it appears that we've succeeded
in returning null from a null-excluding function. That surely won't do.
Luckily, Tucker has already filled the hole: AI05-0032-1 adds "A check
is made that the value of the return object belongs to the function
result subtype.", and that clearly will fail. So at least Constraint_Error
will be raised. (Before AI05-0032-1, we would have had to return null,
as there was no check. Lovely.)
However, it is annoying that we've lost a compile-time check for a reason
that is completely unrelated to the check itself. It also means that
AARM note 6.5(5.g/3) is a lie.
Obviously, fixing the AARM note is easy; this case should be mentioned in
the AARM. But should we tweak the rules to ensure that null exclusion
checks are always made even if the access type is unconstrained (we don't
care about that for this purpose - null exclusions aren't a constraint
anyway)? In that case, the AARM note is fine (and there isn't going
to be a nasty ACATS test...)
****************************************************************
From: Robert A. Duff
Sent: Friday, April 25, 2008 7:50 AM
> Obviously, fixing the AARM note is easy; this case should be mentioned
> in the AARM. But should we tweak the rules to ensure that null
> exclusion checks are always made even if the access type is unconstrained ...
Yes.
****************************************************************
Questions? Ask the ACAA Technical Agent