Version 1.4 of ai05s/ai05-0230-1.txt
!standard 13.3.2(9/3) 10-11-16 AI05-0230-1/02
!class Amendment 10-10-25
!status Amendment 2012 10-11-16
!status ARG Approved 10-0-0 10-10-30
!status work item 10-10-25
!status received 10-10-25
!priority Low
!difficulty Easy
!subject Inheritance of null procedures with preconditions
!summary
Pre and Post aspects may not be specified for null procedures
(Pre'Class and Post'Class may be used).
!problem
There is a problem with pre- and post-conditions (ignoring those
which are unconditionally True) on null procedures because RM 8.3(12.3/2)
assumes that null procedures with the same profile are interchangeable. Thus
it would be possible to inherit two null procedures with different Pre or
Post aspects. Which one is executed then?
!proposal
(See wording.)
!wording
Modify 13.3.2(9/3) [added by AI05-0145-2]:
The Pre or Post aspect shall not be specified for an abstract
subprogram {or a null procedure}. Redunant[Only the Pre'Class
and Post'Class aspects may be specified for such a subprogram.]
!discussion
We could try to allow Pre and Post on concrete null procedures and give such
subprograms preference over those inherited from interfaces. But since a
null procedure doesn't do anything, we can't quite imagine what the Pre and
Post aspects would be useful for. One example was suggested (to prevent calls)
seems to be pushing to runtime a check that ought to be done at compile-time
(by declaring the subprogram abstract). Since the uses are mostly hacks,
we decide that it isn't worth the effort to allow these ever.
We don't know of any other cases where we use some mechanism (e.g., a pragma or an aspect
specification) to cause implicit code generation for a subprogram. Pragma
No_Return is forbidden for a null procedure and an Invariant aspect
specification is illegal for an abstract type (which includes interface types),
so these are not problems.
!corrigendum 13.3.2(0)
Insert new clause:
For a subprogram or entry, the following language-defined aspects may
be specified with an aspect_specification:
[Just to force a conflict, the real text will be in the conflict file.]
!ACATS test
An ACATS B-Test is needed.
!ASIS
There is no ASIS effect to this rule.
!appendix
From: Steve Baird
Sent: Thursday, October 21, 2010 5:56 PM
I think there may be a problem with pre- and post-conditions (ignoring those
which are unconditionally True) on null procedures because RM 8.3(12.3/2)
assumes that null procedures with the same profile are interchangeable. Perhaps
contracts should be forbidden for null procedures which are primitive
subprograms of interface types and 8.2 could be modified to prefer a
not-really-null-because-it-has-a-nontrivial-contract null procedure over other
null procedures.
Does it seem clear that there is a problem here?
Would an example be useful?
Does the proposed solution seem reasonable?
****************************************************************
From: Randy Brukardt
Sent: Thursday, October 21, 2010 6:10 PM
I don't think that banning contracts on certain interfaces is the right way to
go. That just says "if you want to use interfaces, you can't use contracts".
There is already way too much that you can't do with interfaces, it would be
silly to make them even worse.
Besides, the same problem can happen if an abstract routine of an interface has
a contract and a null procedure of a different interface has a contract. Doesn't
the AI already handle the case of multiple contracts from inherited routines (it
would seem like it would have to do that)?
****************************************************************
From: Steve Baird
Sent: Thursday, October 21, 2010 6:25 PM
> ...
>
> I don't think that banning contracts on certain interfaces is the
> right way to go. That just says "if you want to use interfaces, you
> can't use contracts". There is already way too much that you can't do
> with interfaces, it would be silly to make them even worse.
Contracts and interface types play well together using the Pre'Class and
Post'Class aspects, but those are not what I am talking about. I'm talking about
the Pre and Post aspects.
> Besides, the same problem can happen if an abstract routine of an
> interface has a contract and a null procedure of a different interface has a contract.
> Doesn't the AI already handle the case of multiple contracts from
> inherited routines (it would seem like it would have to do that)?
We have a legality rule in the Ai:
The Pre or Post aspect shall not be specified for an abstract
subprogram. Only the Pre'Class and Post'Class aspects may be specified
for such a subprogram.
I am suggesting that this restriction be generalized to also apply to any
primitive subprogram of an interface type.
****************************************************************
From: Randy Brukardt
Sent: Thursday, October 21, 2010 6:42 PM
OK, that makes sense. (I wonder why that wasn't true in the first place??)
****************************************************************
From: Edmond Schonberg
Sent: Friday, October 22, 2010 10:25 AM
> Does it seem clear that there is a problem here?
> Would an example be useful?
> Does the proposed solution seem reasonable?
I should mention that we've had one customer who asked for preconditions on null
procedures. The justification was rather bogus: the precondition was False, to
ensure that any descendants would be forced to override the operation in
question. For this purpose it would have been simpler to make the procedure
abstract. The customer request came before Pre'Class was introduced, so this
would be the proper way to do it now. I agree with Steve's proposal to forbid
Pre and Post on primitives of interfaces, whether they are abstract or null.
****************************************************************
From: Yannick Moy
Sent: Friday, October 22, 2010 10:52 AM
The thing is you cannot have an abstract procedure on a non-abstract type,
right? So if you want to have already some common components shared in the root
type, you have to make the procedure null rather than abstract. Or is there an
idiom to avoid this?
****************************************************************
From: Edmond Schonberg
Sent: Friday, October 22, 2010 11:17 AM
Yes of course, if this is the addition of one primitive to legacy code, giving a
False precondition to a new null primitive allows you to modify the descendant
types incrementally. Everything continues to work as long as you don't call the
primitive in question. If you make the new primitive abstract that forces you to
touch all the descendant declarations. So Pre'Class => False is a reasonable
condition for an ancestor null operation.
****************************************************************
From: Tucker Taft
Sent: Friday, October 22, 2010 11:29 AM
I think the important point is we are talking about restricting use of "Pre" and
"Post" rather than "Pre'Class" and "Post'Class." I think Pre'Class => False
does just what you want, so there is no need for Pre => False.
****************************************************************
From: Steve Baird
Sent: Friday, October 22, 2010 11:45 AM
An abstract type (as opposed to an interface type, which is one special kind of
abstract type) may have components. So the idiom you are looking for, I think,
is to use an abstract non-interface type.
****************************************************************
From: Steve Baird
Sent: Monday, October 25, 2010 12:12 PM
Another case where a null procedure is not ineffective is if it is subject to an
Invariant specification (indirectly, of course, since an Invariant specification
applies to a type, not to a subprogram).
We could extend the definition of ineffective to handle this case, but I just
spent 5 minutes working on this approach and it seemed to be getting pretty
verbose. And pragma No_Return might have easily introduced similar problems (it
didn't, but the point is that we seem to have lots of constructs which cause
implicit code to be generated for subprograms).
So how about replacing the first paragraph above with
An ineffective procedure is defined to be a null procedure which
is a primitive operation of an interface type, or an inherited
subprogram which corresponds (see 3.4) to an ineffective procedure.
If we don't like the term "ineffective", then of course it could be replaced
here and in the 2nd paragraph. Perhaps "strongly null"?
****************************************************************
Questions? Ask the ACAA Technical Agent