Version 1.2 of acs/ac-00086.txt

Unformatted version of acs/ac-00086.txt version 1.2
Other versions for file acs/ac-00086.txt

!standard 12.06(00)          03-12-05 AC95-00086/01
!standard 03.09.02(16)
!standard 03.04.01(05)
!class amendment 03-12-05
!status received no action 03-12-05
!status received 03-10-30
!subject Can't pass limited constants into a generic
!summary
!appendix

!topic "=" on class-wide types as generic actual subprogram
!reference 12.6, 3.9.2(16), 3.4.1(5)
!from Adam Beneschan 10-30-03
!discussion

I've noticed two separate examples lately where publicly available
source code expects a generic formal subprogram named "=" to default
to a subprogram whose parameters are of a class-wide type.  The first
example was briefly discussed here in August, and was posted by the
author, Martin Krischik.  A simplified example:

    generic
       type Item (<>) is abstract tagged private;
       with function "=" (L, R : Item'Class) return Boolean is <>;
    package Pkg is ...

This normally cannot be instantiated with any type unless the actual
for "=" is explicitly specified, because if you instantiate it like
this:

    package New_Pkg is new Pkg (Type_1);

12.6(6) and 8.6(26) say that the actual for "=" must be
type-conformant with the formal subprogram declaration, and since
there is no predefined subprogram with this profile:

    function "=" (L, R : Type_1'Class) return Boolean;

the instantiation will fail unless such a function is explicitly
declared.

A similar example comes from a Doubly_Linked_List package by
R. A. Matthews and is part of the Gapse project.  The generic
declaration is:

    generic
       type Data_Type (<>) is private;
       with function "=" (Left, Right : Data_Type) return Boolean is <>;
    package Doubly_Linked_List is ...

and one of the examples he provides, contains this code:

   type Variant_Type is abstract tagged null record;
   package Variant_Lists is new Doubly_Linked_List (Variant_Type'Class);

This instantiation is illegal for the same reason.

I haven't tried to look at Martin's code closely, but it's pretty
clear how this construct could be useful in the Doubly_Linked_List
case.  One of the functions defined by Doubly_Linked_List is "=" on a
list type, which tests whether all elements of the list are the same.
To do this if the actual for Data_Type is a tagged type, you would
want to use a user-defined "=" function defined for the type;
furthermore, you would want the ability to instantiate with a
class-wide type so you could create a heterogeneous list, and have "="
inside the generic work the same way it would for parameters of a
class-wide type, as described by 3.9.2(16) (returns FALSE if the tags
are different, otherwise dispatches to the correct "=" function).  But
the above won't get the job done.  Note that while 3.9.2(16) defines
how "=" works on classwide parameters, it doesn't cause a predefined
"=" function to be created that could be used as a generic actual
parameter.

Since there are two pieces of public code that try to use this
capability, should the language be modified so that they will work
legally?  I'm thinking that 12.6(10) could be extended to read:

   "If a generic unit has a subprogram_default specified by a box, and
   the corresponding actual parameter is omitted, then it is
   equivalent to an explicit actual parameter that is a usage name
   identical to the defining name of the formal.  If there is no
   visible subprogram that is type-conformant with the profile of the
   formal subprogram, and if the formal subprogram is a function whose
   name is the equality operator, and if the parameters to this
   function are of a class-wide type, then the actual is an implicit
   subprogram whose profile matches the profile of the formal
   subprogram and which returns the result of a function_call on the
   equality operator as defined by 3.9.2(16)."

I'm sure I didn't get the wording quite right, but it could be
something like that.

Comments?

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

From: Tucker Taft
Sent: Thursday, October 30, 2003  9:48 PM

Although class-wide types are generally permitted
as actual types if the formal has unknown discriminants,
the rules are not spelled out clearly in the manual.
The "=" operator is just the tip of the iceberg.
If the formal type is a formal extension, things are
even weirder, since the formal has a full set of
primitives, even though the actual does not.

I think there is an AI which talks about all this,
but in general we have swept this whole area under
the rug, and just hoped that implementors "do the
right thing."

After a little bit of looking, it appears that AI-158
is the one that talks about this.  The current version
of AI-158 is pretty yucky in my view, but the ARG has
not discussed it recently, and I suspect we won't unless
someone forces the issue.  Perhaps Pascal is listening?
How about one more round on AI-158 at the next ARG meeting?

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

From: Randy Brukardt
Sent: Thursday, October 30, 2003 10:19 PM

It was on the agenda for Sydney (it was recently rewritten by Gary
Dismukes). But we didn't look at any regular AIs (well, except 2 really easy
ones in the last 10 minutes of Saturday night). Until we catch up with
amendments, it probably will stay that way.

I'm going to review the regular AIs so that we can use our limited time on
them on the ones that are more likely to matter to users and/or
implementors. But of course those are the hardest.

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

From: Tucker Taft
Sent: Thursday, October 30, 2003  10:48 PM

I think this one is worth some of our time, though maybe not
until the February meeting.  Even ignoring renaming, I can't
find where we describe the semantics of a call on a primitive
in an instantiation using a class-wide actual.  I hope the
semantics are of a wrapper that takes class-wide parameters,
and then does a dispatching call.  I would hope that renaming
is essentially identical to that.  Renaming as body provides
a good model.

I think Adam is essentially asking that when a class-wide type
is an actual, these same kind of wrappers be provided as default
when a formal subprogram matching a primitive of the formal type
has a default of <>, and the (dispatching) primitive of the specific
type associated with the actual class-wide type is directly visible.

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

From: Adam Beneschan
Sent: Friday, October 31, 2003 10:57 AM

Essentially, yes; but one of the examples I provided was a case where
the actual was not a class-wide type:

    generic
       type Item (<>) is abstract tagged private;
       with function "=" (L, R : Item'Class) return Boolean is <>;
    package Pkg is ...

Here there's a problem even if the actual for Item is not a class-wide
type.  I'm not sure whether the same principles apply.

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

From: Tucker Taft
Sent: Friday, October 31, 2003  11:38 AM

I was ignoring that one, because that seems like a clear bug to me.
The user should have written:

   with function "="(L, R : Item) return Boolean is <>;

instead.

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

From: Adam Beneschan
Sent: Friday, October 31, 2003 12:55 PM

Yes, I forgot that in a previous discussion, we agreed that if the
generic formal function is declared with class-wide type parameters,
then any call to "=" in the generic body with parameters of type Item
or Item'Class is ambiguous.

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

From: Martin Krischik
Sent: Sunday, November 2, 2003  5:40 AM

> The user should have written:
>
>    with function "="(L, R : Item) return Boolean is <>;
>
> instead.

I like to point out that I have indeed corrected the statement.

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


Questions? Ask the ACAA Technical Agent