Version 1.1.1.1 of ais/ai-00200.txt

Unformatted version of ais/ai-00200.txt version 1.1.1.1
Other versions for file ais/ai-00200.txt

!standard 03.02.03 (07)          98-03-27 AI95-00200/00
!class binding interpretation 98-03-27
!status received 98-03-27
!priority Low
!difficulty Medium
!subject Generic formal subprograms as dispatching operations
!summary 98-03-27
!question 98-03-27
!recommendation 98-03-27
!wording 98-03-27
!discussion 98-03-27
!appendix

!section 3.2.3(7)
!subject Generic formal subprograms as dispatching operations
!reference RM95-3.2.3(7)
!reference RM95-12.5.1(21)
!reference RM95-12.3(15-16)
!reference RM95-8.3(10)
!reference RM95-3.9.2(1,20)
!reference RM95-8.5.4(12)
!from Todd Allen 98-02-19
!keywords generic formal subprogram, primitive, dispatching
!reference 1998-15801.a Todd Allen 1998-2-19>>
!discussion

The definition of primitive subprograms in 3.2.3(7) suggests that the copies
of generic formal subprograms in an instance can be dispatching operations if
they override any implicitly declared primitive subprograms there.  It is
unclear how dispatching calls on such subprograms should be performed.

For example:

   package P is
      type Root is tagged ...
      -- implicit "="(left, right : Root) return boolean;
      function Foo (l,r : Root) return boolean;
   end P;
   use P;

   generic
      type T is new Root with private;
      -- implicit "="(left, right : T) return boolean;      -- (1)
      -- implicit Foo(left, right : T) return boolean;      -- (2)
      with function "="(l,r : T) returns boolean;           -- (3)
      with function Foo(l,r : T) returns boolean;           -- (4)
   package G is
      procedure Test (X : T'class);
   end G;

   function Bar (l,r : Root) return boolean;

   package I1 is new G(Root, "=", Foo);
   package I2 is new G(Root, Foo, "=");
   package I3 is new G(Root, Bar, Bar);

In each of the instances of G, the declaration of T declares a new view of
Root by RM95 12.3(15).  The predefined "=" operator (1) is copied and is
considered primitive by RM95 12.5.1(21) and RM95 3.2.3(3).  Likewise, the Foo
function (2) is copied and is considered primitive by RM95 12.5.1(21) and
RM95 3.2.3(4).  The user-defined "=" operator (3) and Foo function (4)
declare new views of the generic actual subprograms specified for each
instance.  The "=" (3) and Foo (4) operations are declared in the same
declarative region as the predefined ones (1) and (2) and override them by
RM95 8.3(10).  So, it seems that it should be considered primitive, too, by
RM95 3.2.3(7).

Brief Digression:

   The text in RM95 3.2.3(7) and the text throughout RM95 3.9.2 refer to
   types and subprograms as opposed to views of types and views of
   subprograms.  I have assumed that this was for purposes of brevity.  Many
   of the issues discussed herein also exist for renaming declarations.
   There is a note in RM95 8.5.4(12) which mentions that primitiveness is
   determined by the location of the renaming-as-declaration, as for any
   declaration of (a view of) a subprogram.  This suggests that the "a view
   of" text was intended throughout RM95 3.2.3 and RM95 3.9.2.

Because the "=" (3) and Foo (4) operations are primitive operations of (a
view of) a tagged type in each of the instances, they should also be
dispatching operations by RM95 3.9.2(1).

It is unclear what the effect would be of a dispatching call from within an
instance of G to the "=" (3) or Foo (4) operations.  For example, consider:

   package body G is
      procedure Test (X : T'class) is
      begin
         ... := (X = X);
         ... := Foo(X, X);
      end Test;
   end G;

   ...

   package Q is
      type Extension is new Root with ...;
      -- implicit "="(left, right : Extension) return boolean;
      -- implicit Foo(left, right : Extension) return boolean;
      function Foo (l,r : Extension) return boolean;
   end Q;
   use Q;

   ...

   I1.Test(Extension'(...));
   I2.Test(Extension'(...));
   I3.Test(Extension'(...));

During the execution of I3.Test, the calls to "=" (3) and Foo (4), which are
both views of Bar, should execute the bodies of their corresponding primitive
subprograms of type Extension.  But neither "=" (3) nor Foo (4) nor Bar has a
corresponding primitive subprogram of type Extension.

This confusion throws into doubt the meaning of RM95 3.9.2(20) with respect
to the "=" (3) and Foo (4) operations in I1 and I2, as well.  If the "a view
of" text was intended throughout this paragraph, then the meaning of the
corresponding primitive subprograms of the "=" (3) and Foo (4) operations
becomes unclear in I1.Test and I2.Test.  If the "a view of" text was not
intended there, then presumably the corresponding subprogram of the generic
actual subprogram would be used.  However, this still would not explain what
body should be called in the execution of I3.Test.

Note that a similar problem exists for a formal subprogram overriding the
primitive "=" operator of a formal tagged private type:

   generic
      type T is new tagged private;
      -- implicit "="(left, right : T) return boolean;      -- (1)
      with function "="(l,r : T) returns boolean;           -- (3)
   package G is
      procedure Test (X : T'class);
   end G;

   package body G is
      procedure Test (X : T'class) is
      begin
         ... := (X = X);
      end Test;
   end G;

Also note that a similar problem exists for ordinary subprograms overriding
primitive operations of a generic formal tagged private or generic formal
derived tagged type:

   generic
      type T is new Root with private;
      -- implicit "="(left, right : T) return boolean;      -- (1)
      -- implicit Foo(left, right : T) return boolean;      -- (2)
   package G is
      function "="(l,r : T) returns boolean;                -- (3)
      function Foo(l,r : T) returns boolean;                -- (4)

      procedure Test (X : T'class);
   end G;

   package body G is
      procedure Test (X : T'class) is
      begin
         ... := (X = X);
         ... := Foo(X, X);
      end Test;
   end G;

So, what subprograms should be executed for calls to the "=" (3) and Foo (4)
operations in each of the calls to Test?

--
Todd Allen
Concurrent Computer Corporation
Fort Lauderdale, FL  33309

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

!section 3.2.3(7)
!subject Generic formal subprograms as dispatching operations
!reference RM95-3.2.3(7)
!reference RM95-12.5.1(21)
!reference RM95-12.3(15-16)
!reference RM95-8.3(10)
!reference RM95-3.9.2(1,20)
!reference RM95-8.5.4(12)
!reference 1998-15801.a Todd Allen 98-02-19
!from Tucker taft 98-02-26
!keywords generic formal subprogram, primitive, dispatching
!reference 1998-15806.a Tucker Taft 1998-2-26>>
!discussion

: The definition of primitive subprograms in 3.2.3(7) suggests that the copies
: of generic formal subprograms in an instance can be dispatching operations if
: they override any implicitly declared primitive subprograms there.

This paragraph was not intended to apply to formal subprograms; some
wording improvement is in order.  In any case, the rules for tagged
types are constructed so that where a call on a dispatching subprogram goes is
independent of the location of the call, and is determined entirely
by which conceptual "slot" the specified dispatching operation
occupies.  The rules for calls on primitives of untagged types are
not based on a run-time "slot" but rather on the normal compile-time
visibility rules.  [This is implied by 3.9.2(14,20).  See also
AARM 3.9.2(20.a-20.g).]

The primitive subprograms of a formal type are specified in 12.5(8)
and 12.5.1(21); formal subprograms are not primitive subprograms, even
if they hide primitives of the formal type.

: Brief Digression:

:    The text in RM95 3.2.3(7) and the text throughout RM95 3.9.2 refer to
:    types and subprograms as opposed to views of types and views of
:    subprograms.  I have assumed that this was for purposes of brevity.

Which primitives of a type are visible are determined by of the corresponding
(implicit or explicit) subprogram declarations are visible.
It does not depend on which "view" of the *type* is being used, though
the two might be related because the implicit subprogram declarations
generally happen at the same point as the type declaration (though
not always!).

: ... Many
:    of the issues discussed herein also exist for renaming declarations.
:    There is a note in RM95 8.5.4(12) which mentions that primitiveness is
:    determined by the location of the renaming-as-declaration, as for any
:    declaration of (a view of) a subprogram.  This suggests that the "a view
:    of" text was intended throughout RM95 3.2.3 and RM95 3.9.2.

Yes, that is probably true for the subprograms.  It is not necessary
to insert "a view of" when referring to types.

: Because the "=" (3) and Foo (4) operations are primitive operations of (a
: view of) a tagged type in each of the instances, they should also be
: dispatching operations by RM95 3.9.2(1).

Formal subprograms are not primitives.

: ...

: So, what subprograms should be executed for calls to the "=" (3) and Foo (4)
: operations in each of the calls to Test?

As mentioned above, the rules for calls on dispatching operations are such
that compile-time view is irrelevant.  All that matters is what address
ends up in the "slot" at run-time, and that does not change based on
compile-time view.

: --
: Todd Allen
: Concurrent Computer Corporation
: Fort Lauderdale, FL  33309

--
-Tucker Taft   stt@inmet.com   http://www.inmet.com/~stt/
Intermetrics, Inc.  Burlington, MA  USA

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

!section 3.2.3(7)
!subject Generic formal subprograms as dispatching operations
!reference RM95-3.2.3(7)
!reference RM95-12.5.1(21)
!reference RM95-12.3(15-16)
!reference RM95-8.3(10)
!reference RM95-3.9.2(1,20)
!reference RM95-8.5.4(12)
!reference 1998-15801.a Todd Allen 98-02-19
!from Todd Allen 98-02-26
!keywords generic formal subprogram, primitive, dispatching
!reference 1998-15807.a Todd Allen 1998-2-26>>
!discussion

Tucker,

   Thank you for your quick response to this comment.

>
> This paragraph [3.2.3(7)] was not intended to apply to formal
> subprograms; some wording improvement is in order.  In any case, the
> rules for tagged types are constructed so that where a call on a
> dispatching subprogram goes is independent of the location of the
> call, and is determined entirely by which conceptual "slot" the
> specified dispatching operation occupies.  The rules for calls on
> primitives of untagged types are not based on a run-time "slot" but
> rather on the normal compile-time visibility rules.  [This is
> implied by 3.9.2(14,20).  See also AARM 3.9.2(20.a-20.g).]
>

   This is the answer that I was expecting, and is in fact the interpretation
   that we've implemented.  I agree that the wording needs a little work to
   explicitly exclude formal subprograms as primitives.

>
> The primitive subprograms of a formal type are specified in 12.5(8)
> and 12.5.1(21); formal subprograms are not primitive subprograms, even
> if they hide primitives of the formal type.
>
> Which primitives of a type are visible are determined by of the corresponding
> (implicit or explicit) subprogram declarations are visible.
> It does not depend on which "view" of the *type* is being used, though
> the two might be related because the implicit subprogram declarations
> generally happen at the same point as the type declaration (though
> not always!).
>
> Yes, that is probably true for the subprograms.  It is not necessary
> to insert "a view of" when referring to types.
>

   I agree that the primitives of formal types are well-defined.

   My reason for believing that the "a view of" text was necessary for types
   as well as subprograms turns out to be faulty.  But I still have an issue
   on which I would appreciate some clarification, so I will explain.

   In the instance, the formal type declares a new view of the actual type,
   and the implicit subprograms of the formal type declare new views of the
   primitives of the actual type.  Because the implicit subprograms are new
   views, I believe that primitiveness has to be determined for them
   independently via the rules in 3.2.3(2-7) rather than the on the basis of
   the subprograms of which they are views (rather like subprogram renaming
   declarations).  Upon rereading 3.2.3(2-7), I notice that even if the "a
   view of" text was inserted for types into that section, the implicit
   subprograms in the instance would still not be considered primitive
   (because the view of the type would not be in a package_specification).

   So, how are the implicit subprograms in an instance considered primitive?
   Is it simply because they are copies of the primitives of the formal type?
   Is primitiveness an aspect that is copied from the implicit declarations
   in the generic to the implicit declarations of the instance?

>
> As mentioned above, the rules for calls on dispatching operations are such
> that compile-time view is irrelevant.  All that matters is what address
> ends up in the "slot" at run-time, and that does not change based on
> compile-time view.
>

   Am I correct in assuming that even though the formal subprograms are not
   considered primitive operations, they still override the primitive
   operations for visibility purposes?  This would mean that the formal
   subprograms would be called (in a non-dispatching manner) instead of their
   dispatching counterparts.

   So, in the example in my comment, for calls to Test in each of the
   instances of G, the calls to "=" and Foo would be non-dispatching calls to
   the actual subprograms associated with the formal subprograms.  Is this
   correct?

--
Todd Allen
Concurrent Computer Corporation
Fort Lauderdale, FL  33309

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

!section 3.2.3(7)
!subject Generic formal subprograms as dispatching operations
!reference RM95-3.2.3(7)
!reference RM95-12.5.1(21)
!reference RM95-12.3(15-16)
!reference RM95-8.3(10)
!reference RM95-3.9.2(1,20)
!reference RM95-8.5.4(12)
!reference 1998-15801.a Todd Allen 98-02-19
!reference 1998-15806.a Tucker Taft 98-02-26
!reference 1998-15807.a Todd Allen 98-02-26
!keywords generic formal subprogram, primitive, dispatching
!reference 1998-15808.a Tucker Taft 1998-2-26>>
!discussion

> ...
>    In the instance, the formal type declares a new view of the actual type,
>    and the implicit subprograms of the formal type declare new views of the
>    primitives of the actual type.  Because the implicit subprograms are new
>    views, I believe that primitiveness has to be determined for them
>    independently via the rules in 3.2.3(2-7) rather than the on the basis of
>    the subprograms of which they are views (rather like subprogram renaming
>    declarations).  Upon rereading 3.2.3(2-7), I notice that even if the "a
>    view of" text was inserted for types into that section, the implicit
>    subprograms in the instance would still not be considered primitive
>    (because the view of the type would not be in a package_specification).
>
>    So, how are the implicit subprograms in an instance considered primitive?
>    Is it simply because they are copies of the primitives of the formal type?
>    Is primitiveness an aspect that is copied from the implicit declarations
>    in the generic to the implicit declarations of the instance?

Primitiveness is generally only important for calls on dispatching
operations and when type derivation takes place.
It is certainly the intent that calls on the implicitly declared
primitives of the formal become calls on dispatching operations
if the actual type is tagged.
As far as type derivation, in the instance, deriving from a formal
becomes equivalent to deriving from the actual, which means that
in the instance, you might actually end up with more implicit
declarations.  This is explained in 12.3(16-17).

> > As mentioned above, the rules for calls on dispatching operations are such
> > that compile-time view is irrelevant.  All that matters is what address
> > ends up in the "slot" at run-time, and that does not change based on
> > compile-time view.
> >
>
>    Am I correct in assuming that even though the formal subprograms are not
>    considered primitive operations, they still override the primitive
>    operations for visibility purposes?  This would mean that the formal
>    subprograms would be called (in a non-dispatching manner) instead of their
>    dispatching counterparts.

Yes.

>    So, in the example in my comment, for calls to Test in each of the
>    instances of G, the calls to "=" and Foo would be non-dispatching calls to
>    the actual subprograms associated with the formal subprograms.  Is this
>    correct?

I don't have your example in front of me, but that sounds right.

> --
> Todd Allen
> Concurrent Computer Corporation
> Fort Lauderdale, FL  33309

-Tuck

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

Questions? Ask the ACAA Technical Agent