Version 1.6 of ai12s/ai12-0149-1.txt
!standard 7.3.2(19.3/4) 15-01-22 AI12-0149-1/01
!class binding interpretation 15-01-22
!status Corrigendum 1-2012 15-01-28
!status WG9 Approved 15-06-26
!status ARG Approved 9-0-1 15-01-28
!status work item 15-01-22
!status received 15-01-21
!priority Medium
!difficulty Easy
!qualifier Omission
!subject Type invariants are checked for functions returning access-to-type
!summary
Type invariants are checked for functions whose result is access to
a type with a part of a type with an invariant.
!question
7.3.2(19.3/3) says that the invariant for a type T is checked for
parameters of an access-to-object-containing-a-part-of-T. But there is not
corresponding rules for functions that return access types. That seems to
create a significant hole in the protection provided by type invariants.
Should this hole be plugged? (Yes.)
!recommendation
(See Summary.)
!wording
Modify 7.3.2(19.3/4):
* has an access-to-object parameter {or result} whose designated type has
a part of type T, or
Modify AARM 7.3.2(23.a/3):
Invariant checks on subprogram return are not performed on objects that are
accessible only through access values{ that are subcomponents of some other
object}. It is also possible to call through an access-to-subprogram value and
reach a subprogram body that has visibility on the full declaration of a type,
from outside the immediate scope of the type. No invariant checks will be
performed if the designated subprogram is not itself externally visible.
These cases represent "holes" in the protection provided by invariant checks;
but note that these holes cannot be caused by clients of the type T with the
invariant{. The designer of the package has to declare a visible type with an
access to T subcomponent and use it as a parameter or result to subprograms in
the package, or pass the client an access-to-subprogram value representing a
private operation of the package. In the absence of such things, all values
that the client can see will be checked for a private type or extension.}[
without help for the designer of the package containing T.]
!discussion
As noted in the AARM note above, it is intended that type invariant checks
aren't made on composite types with subcomponents of an
access-to-object-with-part-of-T, only on direct
access-to-object-with-part-of-T. It's not practical to check all such cases,
as one would have to look through all of the access-to-somethings to do so.
Specifically, if we made the rule stronger by including parts of
access-to-object types:
* has a parameter or result with a part of an access-to-object type whose
designated type has a part of type T, or
There would still be an unchecked case for an access-to type with a part of
a access-to part of T. And these cases are getting increasingly unlikely.
In any case, since the checks performed are determined by the declarations
in the visible part of the package containing T, the author of the package
containing T has complete control over whether any holes exist. So long as
they do not define a visible type with a subcomponent that is
access-to-object-with-part-of-T (and do not export any private subprograms
via an access-to-subprogram type), all possible ways for a value to leave
the package will be checked. (There is no problem if a private type
contains a subcomponent of an access type, as any subprogram that provides
access to that component will necessarily have to have a parameter or result
that is itself checked.)
!corrigendum 7.3.2(19/3)
!comment This is just to force a conflict with the wording changes of AI12-0044-1;
!comment the actual wording is in the conflict file.
@drepl
@xi2bull<has an access-to-object parameter whose designated type has a part
of type @i<T>, or>
@dby
@xi2bull<has an access-to-object parameter or result whose designated type has a part
of type @i<T>, or>
@drep
!ASIS
No ASIS effect.
!ACATS test
An ACATS C-Test is needed to check that this check is made.
!appendix
From: Randy Brukardt
Sent: Wednesday, January 21, 2015 8:20 PM
It struck me this morning when thinking about the tests that Jeff still could
write for type invariants that there is a strange-seeming omission in the
checks. Specifically, the rewritten set of checks performed after return from a
subprogram call is:
19.4 and either:
19.1/4 * has a result with a part of type T, or
19.2/4 * has one or more out or in out parameters with a part of type T,
or
19.3/4 * has an access-to-object parameter whose designated type has a
part of type T, or
19.4/4 * is a procedure or entry that has an in parameter with a part of
type T,
It seems strange to me that we check access-to-object parameters that might have
been modified (but probably weren't), but we don't have corresponding rules for
access-to-object results (which are most likely newly created or changed).
That is, shouldn't we also have a bullet:
* has an access-to-object result whose designated type has a part of type T,
or
[I believe that the existing wording of 19.3/4 is intended to apply to both
access parameters (anonymous access-to-object types) as well as parameters with
a named access type, and it makes sense to do the same here.]
An alternative would be just to add "or result" after "parameter" in 19.3/4.
Of course, this is such an obvious omission in the original wording, which we
faithfully reproduced in the rewritten new wording, that I have to wonder if it
was intentional. But I can't figure out any advantage to leaving such an obvious
hole in the type invariant checking, particularly if we are going to require
similar checks on parameters. So I have to conclude that the entire group
reviewed this wording (twice!) without noticing the painfully obvious
non-symmetery. (I plead guilty to having written the entire set of suggested
test objectives for 7.3.2 without noticing the omission, so that's three times
for me. I only thought of it today as I was considering whether it would be easy
to convert one of the tests that Jeff has already written to test the 19.3/4
objective -- which led to wondering why there wasn't a corresponding result
objective.)
****************************************************************
From: Tucker Taft
Sent: Wednesday, January 21, 2015 11:04 PM
I agree this is a hole, and almost certainly not intentional. I think "access
result" is not yet on most people's internal radar screen (not including Steve,
of course ;-). I certainly never think of it when considering feature
interactions...
****************************************************************
From: Randy Brukardt
Sent: Thursday, January 22, 2015 12:24 AM
True enough, although this also should apply to functions returning named access
types. Which should hardly be a foreign concept to anyone. :-)
[Note that the existing rule and its counterpart here don't apply to parts of
composite objects. But that was an intentional hole; we decided to limit the
complication for implementers by not requiring them to find parts of access
types designating T. I distinctly remember discussing that in Edinburgh. AARM
7.3.2(23.a/3) mentions that, but gets it wrong (it's only subcomponents of
access values that aren't checked - it's pretty clear that direct uses of access
values are checked by 7.3.2(19.3/3)). Should fix that as part of this AI as
well. In that note, "help for the designer" should be "help from the designer";
probably that sentence should be broken up and explained better -- something
like "but note that these holes cannot be caused by clients of the type T with
the invariant. The designer of the package has to declare a visible type with an
access to T subcomponent and use it as a parameter or result to subprograms in
the package, or pass the client an access-to-subprogram alue representing a
private operation of the package. In the absence of such things, all values that
the client can see will be checked for a private type or extension."]
****************************************************************
Questions? Ask the ACAA Technical Agent