Version 1.1 of ais/ai-00228.txt

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

!standard 3.09.3 (6)          00-04-10 AI95-00228/00
!class binding interpretation 00-04-10
!status received 00-04-10
!priority Low
!difficulty Medium
!subject Premature use of "must be overridden" subprograms
!summary
!question
!recommendation
!wording
!discussion
!corrigendum xx.xx.xx(0x)
!ACATS 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.

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


Questions? Ask the ACAA Technical Agent