Version 1.1 of acs/ac-00099.txt

Unformatted version of acs/ac-00099.txt version 1.1
Other versions for file acs/ac-00099.txt

!standard 8.3(12)          04-06-02 AC95-00098/02
!standard 8.3(13)
!standard 8.3(26/1)
!class confirmation 04-06-02
!status received no action 04-06-02
!status received 04-05-04
!subject Possible hole related to AI83-00012
!summary
!appendix

!topic Possible hole related to AI83-00012
!reference RM95 3.4(17,23),7.3.1(6),8.3(12,13),12.3(16)
!from Adam Beneschan 04-05-04
!discussion

The following is based on AI83-00012:

      generic
          type T1 is private;
          type T2 is private;
      package GP3 is
          type T is range 1..10;
          procedure PROC (X : T1; Y : T);
          procedure PROC (Z : T2; Y : T);
      end GP3;

      package P3 is new GP3 (INTEGER, INTEGER);

      type NT is new P3.T;

      X1 : P3.T;
      X2 : NT;

   begin
      P3.PROC (X => 5, Y => X1);  -- legal?
      P3.PROC (Z => 5, Y => X1);  -- legal?
      PROC (X => 5, Y => X2);     -- legal?
      PROC (Z => 5, Y => X2);     -- legal?

This AI discusses what happens when instantiation and/or derived types
result in the creation of two subprograms that are homographs.  In the
above case, when the instance P3 is created, it will contain two PROC
procedures that are homographs---both with Integer as the first
parameter and P3.T as the second---but this is allowed by AI83-00012
and explicitly allowed by RM95 8.3(26).  Both PROC's are primitive
subprograms of T.  The wording of 8.3(13) appears to make these
subprograms "implicitly declared".  Later, when NT is derived, both
primitive operations are inherited, so there are two versions of PROC
whose first parameter has type Integer and whose second parameter has
type NT.  They are homographs, and they are implicit.

In both cases (the two PROC's in P3, and the two inherited PROC's
declared for NT), we have two implicit subprograms that are
homographs.  Question: Does 8.3(12) [which was not part of Ada 83 or
AI83-00012] kick in?  This says "An implicit declaration of an
inherited subprogram overrides a previous implicit declaration of an
inherited subprogram".  But is one of them "previous"?  For the first
case, 8.3(13) says "These new declarations occur immediately after the
type declaration", but says nothing about what order they're declared
in, if any.  Similarly, 3.4(23) says that the inherited subprograms
are both declared "immediately after the derived_type_definition", but
there's nothing there that says what order they're declared in.  This
looks like an omission to me; the RM should say something about this.
It seems that one of these should be true:

(1) When more than one inherited subprogram is declared at the same
    place (in 3.4(23) and 7.3.1(6)), the subprograms are declared in
    the same order as they are for the parent type.  This would mean
    that the PROC that takes X as a parameter is overridden by the one
    that takes Z as a parameter, by 8.3(12), and thus the first call
    to PROC is illegal while the second is legal.  If this is the
    case, the RM should say so explicitly.  A similar rule needs to be
    present for the "whole new set of primitive subprograms" in
    8.3(13) and/or 12.3(16), although I'm not sure how it would be
    worded.

(2) When more than one inherited subprogram is declared at the same
    place, none of those subprograms is considered previous to any
    other, so that 8.3(12) does not apply to any two of those
    subprograms.  A similar rule would need to be in 8.3(13) and/or
    12.3(16).

For what it's worth, some of the wording in AI83-00012 seemed to
indicate that any of the homographs should be callable; for a slightly
more complicated case involving a second generic, the AI says:

   (Note that if it is legal, one of the homographs can
   be called by writing P4.PROC(X => ...).)

and I'm sure the author intended this to apply equally to the
procedure whose first parameter is named Z.

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

From: Randy Brukardt
Sent: Wednesday, June 2, 2004  9:17 PM

The wording changes for AI-251 (interface types) have the side effect of
making examples like this illegal. (At least, the author of the AI makes
this claim; I'm not quite certain about this -- it doesn't appear that the
Ada 95 situation is changed to me -- but I don't see why this would be legal
in Ada 95, either. The definition of homographs that neither override nor
hide is illegal by 8.3(26/1).)

Given that the examples are illegal, there isn't any need to figure out what
they mean. The rest of Adam's note makes it clear that we don't want to have
to figure that out!

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

From: Tucker Taft
Sent: Wednesday, June 2, 2004  10:03 PM

> The wording changes for AI-251 (interface types) have the side effect of
> making examples like this illegal. (At least, the author of the AI makes
> this claim; I'm not quite certain about this -- it doesn't appear that the
> Ada 95 situation is changed to me -- but I don't see why this would be legal
> in Ada 95, either. The definition of homographs that neither override nor
> hide is illegal by 8.3(26/1).)

I don't see why Randy thinks this is illegal in Ada 95 or Ada 2000.
I can believe that AI-251 will make it illegal in Ada 200Y.
In Ada 2000, clearly the instantiation is legal.  The derived
type is a more interesting question, but it seems to be legal
as well, presuming one believes the implicit declarations
of inherited subprograms occur in some order, since the latter
implicit declaration will override the earlier one, by 8.3(12).
In any case, there is no part of 8.3(26/1) that makes an overridable
declaration illegal, and clearly both inherited subprograms
of type NT are "overridable."

> Given that the examples are illegal, there isn't any need to figure out what
> they mean. The rest of Adam's note makes it clear that we don't want to have
> to figure that out!

I would say most of the example is legal.  If we believe
that the "second" implicit declaration overrides the
first implicit declaration, then the Proc with formal params
X and Y for type NT is overridden by the Proc with
formal params Z and Y.  I think the subtle order dependence
here is one reason why AI-251 wants to make the derived
type illegal.

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

From: Randy Brukardt
Sent: Wednesday, June 2, 2004  10:23 PM

> I don't see why Randy thinks this is illegal in Ada 95 or Ada 2000.
> I can believe that AI-251 will make it illegal in Ada 200Y.
> In Ada 2000, clearly the instantiation is legal.

I must have missed something.

12.3(11) says that legality rules are rechecked in the visible part of an
instance. 8.3(26/1) is a legality rule. Neither of the two explictly
declared PROCs are overriddable. In the instance, we have:

          procedure PROC (X : Integer; Y : T);
          procedure PROC (Z : Integer; Y : T);

which clearly are illegal homographs by 8.3(26/1). What did I miss??

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

From: Pascal Leroy
Sent: Thursday, June 3, 2004  1:21 AM

> I must have missed something.

> 12.3(11) says that legality rules are rechecked in the visible part of an
> instance. 8.3(26/1) is a legality rule. Neither of the two explictly
> declared PROCs are overriddable. In the instance, we have:

>          procedure PROC (X : Integer; Y : T);
>          procedure PROC (Z : Integer; Y : T);

> which clearly are illegal homographs by 8.3(26/1). What did I miss??

I think you missed the last sentence of 8.3(26/1), which says that all the
rules in this paragraph don't apply in an instance.  In other words, I
agree with Tucker that the instantiation was legal in Ada 95+TC1.  I also
believe that the type derivation was legal, although the language was quite
muddled here, since as Adam pointed out you don't quite know what
operation(s) you get.  The fact that AI 251 makes the type derivation
illegal seems like a good thing in this perspective.

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

From: Randy Brukardt
Sent: Thursday, June 3, 2004  5:44 PM

I apparently had a complete brain lock -- I never saw the derived type in
either AI-251 or the Adam's questions, and never realized that it was being
talked about, not the instantiations. Sigh.

In any case, I think we've proven that Adam's problem is taken care of by Ada
200Y -- which is the important point, because it means we don't have to decide
how it works.

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

From: Adam Beneschan
Sent: Thursday, June 3, 2004  6:54 PM

No, I think we were talking about both.  My original example did ask
about two separate but similar cases: homographs created by an
instantiation, and homographs created by type derivation.  The
instantiation case seems to be legal in Ada 95 because 8.3(26/1) says
that the rules don't apply in an instance.  The derived type case
hasn't been discussed as much, but Tucker explained why he thought it
was legal in Ada 95.  In any case, the change to 8.3(26/1) proposed by
AI-251 does make the derived type case illegal.

After looking at this more closely, I think I blew it when discussing
the instantiation case.  I cited 8.3(12), but that rule applies only
to inherited subprograms, and there weren't any in my example (looking
at just the instantiation).  Here's another case:

      generic
          type T1 is private;
          type T2 is private;
      package GP3 is
          type T is range 1..10;
          procedure PROC (X : T1; Y : T);
          procedure PROC (Z : T2; Y : T);
          type NT is new T;
      end GP3;

      package P3 is new GP3 (INTEGER, INTEGER);

Now, when P3 is created, these inherited subprograms are created
inside P3:

      procedure PROC (X : INTEGER; Y : NT);
      procedure PROC (Z : INTEGER; Y : NT);

AI-251 doesn't make this illegal because the last sentence of the
proposed replacement for 8.3(26/1) still means that the rule doesn't
apply in an instance, when the operations aren't dispatching.  So I
think in this case, my question seems to remain unanswered: in the
instance P3, does one of the inherited PROC procedures in the instance
override the other (by 8.3(12)) even though they weren't homographs in
the generic?  Or do we say neither one is considered "previous" to the
other, for the purposes of 8.3(12)?

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

From: Randy Brukardt
Sent: Thursday, June 3, 2004  7:59 PM

I would be very opposed to even trying to answer this question, because of the
likelyhood of causing unintended consequences from fiddling with the homograph
rules. (AI-251 is bad enough.)

That's especially true because this is really bad code piled on bad code.
Deriving user routines for an untagged type is almost always a mistake and
unintended -- I'd prefer that doing so was illegal (but that would be too
incompatible). Similarly, the only reason that these instantiations are allowed
in the first place is compatibility with Ada 83 (Ada 83 didn't really have
checks for legal instantiations, so this was allowed; Ada 95 has a better model
of checking, and there is no reason that this couldn't be detected). So I'd
prefer to repeal the last sentence of 8.3(26/1) -- but again, that won't fly
because of compatibility reasons.

Given that this code is junk, whatever a compiler does is fine -- there's no
portability issue with junk code. If the programmer insists on pointing a
bazooka at their foot, they shouldn't be surprised if their foot disappears.
The ARG has better things to do than determine which foot they blow away.

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

From: Michael F. Yoder
Sent: Saturday, June 5, 2004  1:46 PM

I considered ignoring this on the basis that it's just a difference of
opinion, but after all I think it's worth objecting: the claim is
incorrect.  Why on earth should deriving from an untagged type be bad,
but deriving from a tagged type be good?  Deriving from any such type is
at least as likely to be using strong typing for what it's intended, as
to be an error.  I've written code that looked much like the above; the
old and new types were time types, and it was important to distinguish
them because one was meant to be monotonic and the other not.  (The
package in question, though, didn't have any potential homograph
problems that I recall.)

As far as the instantiation is concerned, as a user I'm reluctant to
endorse a rule that makes instantiations illegal if they cause
homographs; and I'd much prefer when one operation overrides another,
that which is victorious be constant across implementations.  But I
could probably live with a regime that mandated using a new type,
derived from Integer, to instantiate with two types structurally
identical to Integer in the above case.

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

From: Randy Brukardt
Sent: Saturday, June 5, 2004  4:41 PM

I wasn't referring to derivation per-se, but deriving with primitive
subprograms. Those can be dangerous, because they have many bad properties:
they re-emerge in generics, they prevent the use of rep. clauses on the
derived type, etc. None of the bad properties apply to tagged types (as
Tucker likes to say, they work "right").

Every time that I've derived primitive subprograms of an untagged type, it
has been unintentional; I would have rather that the subprograms weren't
derived at all.

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

From: Nick Roberts
Sent: Saturday, June 5, 2004  9:07 PM

> I wasn't referring to derivation per-se, but deriving with primitive
> subprograms.

That seems like a weird statement, frankly. When does one ever derive a type
that has no primitive operations?

> Those can be dangerous, because they have many bad properties:
> they re-emerge in generics,

Isn't there an amendment proposal to rectify this problem?

> they prevent the use of rep. clauses on the derived type,

This restriction could conceivably be repealed.

> etc.

Well, what is the "etc.", please?

> None of the bad properties apply to tagged types (as Tucker likes
> to say, they work "right").
>
> Every time that I've derived primitive subprograms of an untagged
> type, it has been unintentional; I would have rather that the
> subprograms weren't derived at all.

Does that include declarations such as:

   type T is range A..B;

which are, of course, also a kind of derivation?

Take a look at the OMG IDL mapping for Ada, Randy. It's stuffed with
non-tagged type derivations, as is just about any big software 'layer' or
binding in Ada. They are a major language tool, very far from being
dispensible or mistaken.

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

From: Randy Brukardt
Sent: Monday, June 7, 2004  3:13 PM

> That seems like a weird statement, frankly. When does one ever derive a type
> that has no primitive operations?

I was referring to user-defined privitive operations, of course. Predefined
primitives aren't interesting.

> > Those can be dangerous, because they have many bad properties:
> > they re-emerge in generics,
>
> Isn't there an amendment proposal to rectify this problem?

No, it was determined to be too incompatible. There are actually programs
which depend on re-emergence. (Which seems to me to be doubling the error,
but whatever.)

> > they prevent the use of rep. clauses on the derived type,
>
> This restriction could conceivably be repealed.

I've tried. There is a strong feeling that there should not be expensive
conversions implicitly occurring in calls. (Janus/Ada actually supported
this; we missed the rule that makes it illegal for years.)

...
> > Every time that I've derived primitive subprograms of an untagged
> > type, it has been unintentional; I would have rather that the
> > subprograms weren't derived at all.
>
> Does that include declarations such as:
>
>    type T is range A..B;
>
> which are, of course, also a kind of derivation?

Of course not; this isn't a "derived type declaration", which only can
happen via a "derived_type_declaration" (i.e. "new"). And in any case, I was
only talking about user-defined subprograms (they're the only ones with that
bad properties mentioned above), and certainly this doesn't have any.

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


Questions? Ask the ACAA Technical Agent