Version 1.4 of ais/ai-00228.txt

Unformatted version of ais/ai-00228.txt version 1.4
Other versions for file ais/ai-00228.txt

!standard 3.09.3 (6)          02-01-23 AI95-00228/01
!class binding interpretation 00-04-10
!status work item 02-01-23
!status received 00-04-10
!priority Low
!difficulty Medium
!qualifier Clarification
!subject Premature use of "must be overridden" subprograms
!summary
A subprogram which 'shall be overridden' in the sense of 3.9.3(6) is subject to the same restrictions as an abstract subprogram.
!question
AI95-00211 states that "the 'shall be overridden' property of 3.9.3(6) applies to a renamed view. Thus, any renaming of an inherited subprogram that must be overridden is illegal."
It seems that this formulation is incomplete, and that AI95-00211 should have covered some other cases. Consider the following example, derived from the one in the AI:
package Types is type T is abstract tagged null record; function F return T; generic type NT is new T with private; with function NF return NT; procedure G; end Types;
with Types; package Extensions is type E is new Types.T with null record; type A is access function return E; X : A := F'access; -- Legal? (No.) procedure I is new Types.G (E, F); -- Legal? (No.) function F return E; end Extensions;
Hopefully the lines marked "Legal?" are actually illegal, otherwise it would be possible to create a reference to or call such a 'shall be overridden' subprogram.
These are only some of the constructs that can cause trouble. Between the place where E is declared and the place where F is overridden, it is for instance possible to use E as a generic actual parameter (and one wonders if the generic is able to call the inherited F) or to derive from E (and one wonders if the derived type inherits F, and if the inherited subprogram has the 'shall be overridden' property).
!recommendation
(See Wording.)
!wording
Replace 3.9.3(4) by:
For a derived type, if the parent or ancestor type has an abstract or insubstantial primitive subprogram, or a primitive function with a controlling result, then:
Replace the first sentence of 3.9.3(6) with:
Otherwise, the subprogram is _insubstantial_; an insubstantial subprogram shall be overridden with a nonabstract subprogram; [for a type declared in the visible part of a package, the overriding may be either in the visible or the private part.]
Replace 3.9.3(7) by:
A call on an abstract or insubstantial subprogram shall be a dispatching call; [nondispatching calls to an abstract or insubstantial subprogram are not allowed.]
Replace the second sentence of 3.9.3(9) with:
If a generic formal type is abstract, then for each primitive subprogram of the formal that is neither abstract nor insubstantial, the corresponding primitive subprogram of the actual shall neither be abstract nor insubstantial.
Replace 3.9.3(11) by:
A generic actual subprogram shall not be an abstract or insubstantial subprogram. The prefix of an attribute_reference for the Access, Unchecked_Access, or Address attributes shall not denote an abstract or insubstantial subprogram.
!discussion
The subprograms which have the 'shall be overridden' property of 3.9.3(6) are very similar to abstract subprograms. However, they are not defined as abstract. This is quite strange, because it seems that all the rules in 3.9.3 which have to do with abstract subprograms would be applicable to these 'shall be overridden' subprograms. This is true in particular of 3.9.3(4), 3.9.3(7), 3.9.3(9), and 3.9.3(11).
We have two options. Either we change 3.9.3(6) to state that the 'shall be overridden' subprograms are actually abstract, and all the rules in 3.9.3 now prevent nasty usages of these subprograms. Or we invent a new term to designate them, and we complement some of the rules in 3.9.3 to forbid the usages that are known to be problematic.
Archeology indicates that in version 4.0 of RM95, the rules of 3.9.3(6) were phrased in terms of abstract subprograms, and this was changed in version 5.0 of RM95. This seems to indicate that the 4.0 formulation was inadequate; this is probably because this formulation had the consequence that nonabstract tagged types could have abstract subprograms.
So we decide to create new terminology and fix various rules in 3.9.3: the subprograms covered by 3.9.3(6) are dubbed "insubstantial", and we change some rules to say "abstract or insubstantial".
!corrigendum 3.9.3(4)
Replace the paragraph:
For a derived type, if the parent or ancestor type has an abstract primitive subprogram, or a primitive function with a controlling result, then:
by:
For a derived type, if the parent or ancestor type has an abstract or insubstantial primitive subprogram, or a primitive function with a controlling result, then:
!corrigendum 3.9.3(6)
Replace the paragraph:
by:
!corrigendum 3.9.3(7)
Replace the paragraph:
A call on an abstract subprogram shall be a dispatching call; nondispatching calls to an abstract subprogram are not allowed.
by:
A call on an abstract or insubstantial subprogram shall be a dispatching call; nondispatching calls to an abstract or insubstantial subprogram are not allowed.
!corrigendum 3.9.3(9)
Replace the paragraph:
If a partial view is not abstract, the corresponding full view shall not be abstract. If a generic formal type is abstract, then for each primitive subprogram of the formal that is not abstract, the corresponding primitive subprogram of the actual shall not be abstract.
by:
If a partial view is not abstract, the corresponding full view shall not be abstract. If a generic formal type is abstract, then for each primitive subprogram of the formal that is neither abstract nor insubstantial, the corresponding primitive subprogram of the actual shall neither be abstract nor insubstantial.
!corrigendum 3.9.3(11)
Replace the paragraph:
A generic actual subprogram shall not be an abstract subprogram. The prefix of an attribute_reference for the Access, Unchecked_Access, or Address attributes shall not denote an abstract subprogram.
by:
A generic actual subprogram shall not be an abstract or insubstantial subprogram. The prefix of an attribute_reference for the Access, Unchecked_Access, or Address attributes shall not denote an abstract or insubstantial subprogram.
!ACATS test
A B-Test should be created to test these rules, possibly added to an existing test.
!appendix

From: Pascal Leroy
Sent: Friday, April 07, 2000 3:16 AM

I am trying to implement AI95-00211 (now that we have ACATS tests for AIs ;-)
and it seems to me that there is one case missing from this AI.

The interesting part of AI95-00211 is this:

"Can a subprogram which must be overridden in the sense of 3.9.3(6) be renamed?
(No.)"

The referenced paragraph, 3.9.3(6), states that:

"For a derived type, if the parent or ancestor type has an abstract primitive
subprogram, or a primitive function with a controlling result, then ... the
subprogram shall be overridden with a nonabstract subprogram..."

It seems to me that AI95-00211 should also forbid the use of such a subprogram
as the prefix of attributes 'Access and 'Unchecked_Access.  Here is an example,
derived from the one in the AI, which shows that you can use 'Access to squirrel
away one of these "must be overridden subprogram":

package Types is
    type T is tagged null record;
    function F return T;
end Types;

with Types;
package Extensions is
    type E is new Types.T with null record;
    type A is access function return E;
    X : A := F'Access; -- Legal? Hopefully not!
    function F return E;
end Extensions;

Note that an abstract subprogram cannot be used as the prefix of 'Access
(3.9.3(11)) but this doesn't help because these "must be overridden" subprograms
are not abstract.

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

From: Tucker Taft
Sent: Friday, April 07, 2000 7:44 AM

Pascal Leroy wrote:
> ...
> It seems to me that AI95-00211 should also forbid the use of such a subprogram
> as the prefix of attributes 'Access and 'Unchecked_Access.

And 'Address, and presumably any attribute.

Probably the simplest thing would be to say that the implicitly declared
(inherited) function is abstract.  Why didn't we say that?  Then presumably you
*could* rename them, and you would just get an abstract function.

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

From: Pascal Leroy
Sent: Friday, April 07, 2000 7:56 AM

> Probably the simplest thing would be to say that the implicitly declared (inherited)
> function is abstract.  Why didn't we say that?  Then presumably you *could* rename
> them, and you would just get an abstract function.

That crossed my mind, but I don't think it works.  Consider:

    package P1 is
        type T1 is abstract tagged null record;
        procedure P (X : T1) is abstract;
    end P1;

    with P1;
    package P2 is
        type T2 is new P1.T1 with null record;
    private
        procedure P (X : T2);
    end P2;

    with P2;
    package P3 is
        type T3 is new P2.T2 with null record;
    end P3;

If you say that P2.T2 inherits an abstract P which is later overridden by the
declaration in the private part, then presumably P3.T3 also inherits an abstract
P, which then would have to be overridden.  This is substantially different from
what 3.9.3(6) is currently saying.  These "must be overridden" subprograms are
very weird.

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

From: Tucker Taft
Sent: Friday, April 07, 2000 2:21 PM

There are no functions in your example.  What exactly are you
trying to illustrate?  Can you try to be more explicit?
In general, we know that a non-abstract type has no abstract
primitives, even if the non-abstract ones are declared in the private part.
The same would hold true for functions with a controlling result,
though it wouldn't be as interesting, since they always become
abstract again, even if they are overridden with a non-abstract
function.  Making the inherited function abstract seems to
simplify the description to me, so I guess you need to explain
the problem again.

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

From: Pascal Leroy
Sent: Monday, April 10, 2000 5:10 AM
> In general, we know that a non-abstract type has no abstract
> primitives, even if the non-abstract ones are declared in the private part.

Good point.  I withdraw my objection.

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

To: Randy Brukardt
Sent: Monday, April 10, 2000 6:12 PM

> Probably the simplest thing would be to say that the implicitly declared
> (inherited) function is abstract.  Why didn't we say that?  Then presumably
> you *could* rename them, and you would just get an abstract function.

I agree here with Pascal(1) (and not Pascal(2)!) -- I don't think this works.

This rule appeared very late in the game; it appears to have been added to
RM9X;5.0 (it isn't in 4.0). Prior to that, these things *were* abstract. I would
be very cautious about trying to resurrect a rule that didn't work then.

The point of this rule is to insure that a non-abstract tagged type has no
abstract operations. (Tucker claims this as a statement of fact, but it is in
fact this rule (3.9.3(6)) that guarentees that property; any change to this rule
may very well void that property.)

You could, of course, make 3.9.3(5) true for all types, then add a "must be
overridden" rule for any abstract operation of a non-abstract, tagged type.
Since that is the obvious way to get from RM9X;4.0 to the current rules, I have
to think that it doesn't work for some reason.

It is important to note that you *can* rename a "must be overridden" subprogram,
the issue is that the resulting subprogram still needs to be overridden (so it
is illegal for that reason). (And trying to override it causes illegal
homographs, so it cannot be made legal.) Changing the subprograms to be
"abstract" doesn't change this at all.

---

The interesting question is whether there is a real problem here at all. A
renaming is illegal because the needed overridding can't be given. There is no
such problem with attributes (nor with generic actual subprograms, the other
case covered in 3.9.3(11), which also should be covered by any rule coming out
of this discussion). We know that there must be a concrete subprogram at some
point (because of the "must be overridden" rule). Using it as the prefix to an
attribute might annoy a [mostly] one-pass compiler, but I don't see how that is
different than using a subprogram whose body hasn't been seen yet.

That is, to extend Pascal's original example:

package Types is
    type T is tagged null record;
    function F return T;
end Types;

with Types;
package Extensions is
    type E is new Types.T with null record;
    type A is access function return E;
    function F2 return E;
    Y : A := F2'Access; -- Legal? Of course.
    X : A := F'Access; -- Legal? Why not?
    function F return E; -- (1).
end Extensions;


The use of F2 in 'Access is legal. So why shouldn't the use of F in 'Access be
legal? We know that the overridding at (1) exists; otherwise the unit Extensions
is illegal anyway. And assuming the the overridding exists, how is this
different than F2? I can't find any reason.

Have I missed something?

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

From: Pascal Leroy
Sent: Tuesday, April 11, 2000 3:46 AM

Well, there are two problems here.

The first problem is that surely the implicit F (the one that must be
overridden) and the explicit F (the one that overrides) are different
subprograms (otherwise we wouldn't be talking about overriding, right?).  Now we
have this rule that "two access-to-subprogram values are unequal if they
designate different subprograms" (4.5.2(13)).  Your proposal violates this rule,
because you are saying that the 'Access attribute will return the same value for
both Fs.  That's distinctly ugly.

The second problem is more serious, and that's what got me started.  Once you
have built an access-to-subprogram value that designates one of these
must-be-overridden subprograms, you can use it in a renaming, as in:

    X : A := F'Access; -- Legal? Randy says yes.
    function G return E renames X.all; -- Legal?  Randy is busy trying to solve the halting problem.
    function F return E;

Now the interesting question is: is G one of these must-be-overridden
subprograms?  Because the subprogram name is dynamic, you have no way to tell.
But of course, this directly affects the legality of the program, because you
have to either accept or reject the renaming.  (Now you should see the
relationship with AI 211.)

Note that abstract-ness is another property that (1) influences legality and (2)
propagates through renamings, but in the case of abstract subprograms we know
that a dynamic name cannot designate an abstract subprogram (3.9.3(11)) so we
know that the function G above is never abstract.  That's why I believe that the
only option is to make 'Access illegal for these must-be-overridden subprograms.

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

From: Randy Brukardt
Sent: Tuesday, April 11, 2000 12:08 PM


> Well, there are two problems here.
>
> The first problem is that surely the implicit F (the one that
> must be overridden) and the explicit F (the one that
> overrides) are different subprograms (otherwise we wouldn't
> be talking about overriding, right?).  Now we have this rule
> that "two access-to-subprogram values are unequal if they
> designate different subprograms" (4.5.2(13)).  Your proposal
> violates this rule, because you are saying that the 'Access
> attribute will return the same value for both Fs.  That's
> distinctly ugly.

Well, I'm saying that F'Access designates the concrete subprogram. So of course
it would have the same value. This is the same subprogram that a call to F would
execute. I don't find this weird; tagged types (which these must be) already
have that semantics for calls of subprograms overridden in the private part. So
I'm not suggesting anything new here.

> The second problem is more serious, and that's what got me
> started.  Once you have built an access-to-subprogram value
> that designates one of these must-be-overridden subprograms,
> you can use it in a renaming, as in:
>
>     X : A := F'Access; -- Legal? Randy says yes.
>     function G return E renames X.all; -- Legal?  Randy is
> busy trying to solve the halting problem.
>     function F return E;
>
> Now the interesting question is: is G one of these
> must-be-overridden subprograms?  Because the subprogram name
> is dynamic, you have no way to tell.  But of course, this
> directly affects the legality of the program, because you
> have to either accept or reject the renaming.  (Now you
> should see the relationship with AI 211.)

No, I don't actually see any relationship with AI 211; I don't agree with any of
this. The properties of G come from the "designated subprogram" of A, which
certainly is not a "must be renamed" entity. So G is always legal, and certainly
does not require any overriding. That is true for any renaming, I don't know why
you think that it ought to be different for this case.

Any such property is "lost" when the 'Access is taken. And clearly a 'Access can
only refer to a "concrete" subprogram - it either refers to the overriding
subprogram or it has to be illegal somehow. Since there is no support in the RM
for the latter, I was suggesting that the former was intended.

> Note that abstract-ness is another property that (1)
> influences legality and (2) propagates through renamings, but
> in the case of abstract subprograms we know that a dynamic
> name cannot designate an abstract subprogram (3.9.3(11)) so
> we know that the function G above is never abstract.  That's
> why I believe that the only option is to make 'Access illegal
> for these must-be-overridden subprograms.

Well, I don't agree that F'Access references the "must-be-overridden"
subprogram. Certainly a call to F references the concrete routine (put this
before the declaration of F2 in the example, assume a default initialized object
of it in the body of Extensions):

    type Rec is record
       Comp : E := F; -- Must reference the concrete routine,
                      -- not the "must-be-overridden" one.
    end record;

So why should 'Access be different?


In all honesty, I really don't care about this issue that much. I was just
trying to figure out why the manual was the way it was. Since RM9X;4.0 has
pretty much the semantics that Tucker is suggesting, I was trying to figure out
why it was changed, and in particular, why it was changed away from simply
requiring overriding of any inherited abstract routines. I have to assume that
there was some important reason for this change, so changing it back is
something we should not do without knowing the reasons for the initial change.

A shakier assumption is that the issues of premature use was considered when the
change was made. It seems hard to believe that an entire new concept was
introduced without any consideration of uses of the subprograms. Thus, I find
that there must have been an intent that these things work -- I'm just trying to
figure out what they mean. And it turns out that that meaning is not
inconsistent with the rest of the language.

I know that is a shaky argument (as arguments from intent usually are).
Hopefully, Bob or Tucker will help out here.

In any case, I am not adverse to adding 3.9.3(11) language to
"must-be-overridden" subprograms. "Before the subprogram is overridden, the
subprogram may not be used as a generic actual subprogram or as the prefix of an
attribute reference for the Access, Unchecked_Access, or Address attributes."
(But, does this cause problems for generic formal types, where the subprogram is
not required to be overridden until instantiation??) But I don't think it is
strictly necessary to have a consistent semantics.

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

From: Pascal Leroy
Sent: Tuesday, April 11, 2000 3:30 PM

> No, I don't actually see any relationship with AI 211; I don't agree with
> any of this. The properties of G come from the "designated subprogram" of A,
> which certainly is not a "must be renamed" entity. So G is always legal, and
> certainly does not require any overriding. That is true for any renaming, I
> don't know why you think that it ought to be different for this case.

So you are telling me that the following ought to be legal:

     X : A := F'Access;
     function G return E renames X.all;
     function F return E;

but obviously AI 211 says that the following is illegal:

     function G return E renames F;
     function F return E;

so much for consistent language design!  If your program is rejected because
of AI 211, just add an extra access-to-subprogram variable, it makes it
legal (and so much more readable).

> Well, I don't agree that F'Access references the "must-be-overridden"
> subprogram. Certainly a call to F references the concrete routine (put this
> before the declaration of F2 in the example, assume a default initialized
> object of it in the body of Extensions):
>
>     type Rec is record
>        Comp : E := F; -- Must reference the concrete routine,
>                       -- not the "must-be-overridden" one.
>     end record;
>
> So why should 'Access be different?

I don't care about dynamic semantics, I am talking name resolution and
legality rules.  In the above expression, the name F designates the
subprogram that will be overridden; it happens that at execution you call
the overriding one, but in this language we try to precisely define the
meaning of a name as opposed to what happens at execution.

If you say that the name F in F'Access references the overriding subprogram,
you are introducing a case where a name references an entity which has not
been declared yet.  This is something entirely new, and it's going to break
more that one compiler (for no good reason).

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

From: Randy Brukardt
Sent: Tuesday, April 11, 2000 6:44 PM

> I don't care about dynamic semantics, I am talking name resolution and
> legality rules.

But it is only the dynamic semantics that matters. There is no name resolution
or legality problem here.

> In the above expression, the name F designates the
> subprogram that will be overridden; it happens that at execution you call
> the overriding one, but in this language we try to precisely define the
> meaning of a name as opposed to what happens at execution.
> If you say that the name F in F'Access references the overriding subprogram,
> you are introducing a case where a name references an entity which has not
> been declared yet.  This is something entirely new, and it's going to break
> more that one compiler (for no good reason).

That is not what I meant at all. I said that F'Access returns the overriding
subprogram -- I suppose that is the dynamic semantics. F is the
must-be-overridden subprogram - that is the name resolution. That is precisely
the meaning of a call to F (as I demonstrated earlier) -- why should F'Access
not be usable when a call is?

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


Questions? Ask the ACAA Technical Agent