Version 1.1 of ai05s/ai05-0131-1.txt

Unformatted version of ai05s/ai05-0131-1.txt version 1.1
Other versions for file ai05s/ai05-0131-1.txt

!standard 12.6(10)          08-12-04 AI05-0131-1/01
!class binding interpretation 08-12-04
!status work item 08-12-04
!status received 08-10-23
!priority Low
!difficulty Medium
!qualifier Omission
!subject Class-wide operations for formal subprograms revisited
!summary
** TBD **
!question
AI05-0071-1 allows an instantiation to automatically create a matching subprogram for a class-wide type if a primitive for the specific type is directly visible.
However, this requires using a use clause to get the proper visibility, which can clutter the visibility with many unrelated subprograms. Moreover, the capability is not available if the subprogram is directly specified in the instantiation.
It is very unusual in Ada to be able to do something by default that you cannot do explicitly.
Should this be corrected?
!recommendation
(See Summary.)
!wording
** TBD **
[I didn't try to figure out wording for this one. It would seem to be necessary to take the wording added to 12.6(10) by AI05-0071-1 and move it up to a separate paragraph preceding 12.6(10) so it would apply to all (non-abstract) formal subprograms - Editor]
!discussion
Consider an example like:
package Pack1 is type Root is tagged record F1 : Integer; end record; procedure Oper_1 (X : in out Root); end Pack1;
package Pack2 is generic type T(<>) is private; with procedure Oper_1 (X : in out T) is <>; package Gen_Pack is end Gen_Pack; end Pack2;
with Pack1; with Pack2; package Pack3 is package Inst1 is new Pack2.Gen_Pack (Pack1.Root); -- ERROR: package Inst2 is new Pack2.Gen_Pack (Pack1.Root'Class); -- ERROR: package Inst3 is new Pack2.Gen_Pack (Pack1.Root, Pack1.Oper_1); -- OK package Inst4 is new Pack2.Gen_Pack (Pack1.Root'Class, Pack1.Oper_1); -- ERROR: use Pack1; package Inst5 is new Pack2.Gen_Pack (Pack1.Root); -- OK package Inst6 is new Pack2.Gen_Pack (Pack1.Root'Class); -- OK end Pack3;
Inst1 is illegal because Oper_1 is not directly visible at the point of the instantiation. Inst2 is illegal for a similar reason. The use clause makes the similar Inst5 and Inst6 legal, the latter because of the new rules of AI05-0071-1.
But if you want to explicitly give the subprogram (perhaps because the use clause drags in lots of other conflicting names), Inst3 is legal (of course), but Inst4 is not.
Ada almost always allows using selected notation rather than use visibility (it even goes so far as to provide selection notation for operators!), but that is not the case here. That seems to be a mistake.
--!corrigendum 12.6(10/2)
!ACATS Test
An ACATS C-test should test the revised rule.
!appendix

!topic Should AI05-0071 allow renaming subprograms?
!reference AI05-0071
!from Adam Beneschan 08-10-23
!discussion

The language of AI05-0071 allows for a generic to be instantiated with a
class-wide type, and will allow the actuals for generic formal subprograms
to be dispatching subprograms "created" by the compiler, in a sense.  However,
the language of AI05-0071 allows for this only if the operation is a primitive
subprogram that is directly visible. 

I'm wondering whether this should be expanded a bit to allow renames.
Consider this example, which doesn't involve instantiation with class-wide
types:

    package Pack1 is
        type Root is tagged record
            F1 : Integer;
        end record;
        procedure Oper_1 (X : in out Root);
    end Pack1;

    package Pack2 is
        generic
            type T(<>) is private;
            with procedure Oper_1 (X : in out T) is <>;
        package Gen_Pack is
        end Gen_Pack;
    end Pack2;

    with Pack1;
    with Pack2;
    package Pack3 is
        package Inst is new Pack2.Gen_Pack (Pack1.Root);  -- ERROR:
    end Pack3;

This won't compile, because for the generic formal subprogram default to be used,
Oper_1 would have to be visible.  This can be accomplished with USE or USE TYPE.
But another way, if it is undesirable to make everything directly visible that
USE or USE TYPE would make visible, would be to use a rename:

    package Pack3 is
        procedure Oper_1 (X : in out Pack1.Root) renames Pack1.Oper_1;
        package Inst is new Pack2.Gen_Pack (Pack1.Root);
    end Pack3;

This option doesn't appear to be available in the class-wide type case: 

    package Pack3 is
        procedure Oper_1 (X : in out Pack1.Root) renames Pack1.Oper_1;
        package Inst is new Pack2.Gen_Pack (Pack1.Root'Class);
    end Pack3;

The new language that AI05-0071 adds to 12.6(10) wouldn't apply because this
subprogram rename isn't a primitive subprogram, and the subprogram that it
renames, which is a primitive subprogram, is still not directly visible.

It may not be the worst problem in the world, and you can work around it, but it's
a little ugly:

    package Pack3 is
        package Dummy_Nested is
            use type Pack1.Root;
            package Inst is new Pack2.Gen_Pack (Pack1.Root'Class);
        end Dummy_Nested;
        package Inst renames Dummy_Nested.Inst;
    end Pack3;

But should 12.6(10) as modified by this AI be modified to allow directly visible
subprograms that are renames of primitive subprograms, as well as directly visible
primitive subprograms?

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

From: Adam Beneschan
Date: Thursday, October 23, 2008 12:34 PM

> This won't compile, because for the generic formal subprogram default 
> to be used, Oper_1 would have to be visible.  This can be accomplished 
> with USE or USE TYPE.

Ummm, my bad.  USE TYPE wouldn't work in the above case, but it would work
if the subprogram were an operator.  This actually makes the problem potentially
a little worse than I thought, since it means that in the AI95-71 case, if the
subprogram isn't an operator, you'd have to use USE instead of USE TYPE to make
it directly visible, and there could be even more objection to that since it
could make many other things directly visible.

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

From: Tucker Taft
Date: Thursday, October 23, 2008 12:42 PM

I don't see the need.  This is a tricky enough implementation area as it is,
so trying to wedge renames into this seems like overkill.  By the way, a
"use type" wouldn't help here because we aren't talking about an operator.

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

From: Randy Brukardt
Date: Friday, October 24, 2008  7:39 PM

Those of us from the society of use-adverse programmers would beg to differ.

But I don't want renames, either, the problem in my mind is that the magic
doesn't work for an explicit routine (only one that is defaulted). This is
about the only case in Ada that I can think of where that is true.

In Adam's example, I almost certainly would have given the parameter explicitly
rather than insert a use clause:

  with Pack1;
  with Pack2;
  package Pack3 is
      package Inst is new Pack2.Gen_Pack (Pack1.Root, Pack1.Oper_1);
  end Pack3;

which is a lot less work (and maintainance issues) than a renames!

But the equivalent:

  with Pack1;
  with Pack2;
  package Pack4 is
      package Inst is new Pack2.Gen_Pack (Pack1.Root'Class, Pack1.Oper_1);
             -- ERROR:
  end Pack4;

is illegal, because Oper_1 doesn't match. The only choices are to put in a
full use clause (no way) or to define your own Oper_1 (note that I don't see
any value to a rename here, either, the full routine isn't much longer):

  with Pack1;
  with Pack2;
  package Pack4 is
      procedure Oper_1 (X : in out Pack1.Root'Class);
      package Inst is new Pack2.Gen_Pack (Pack1.Root'Class, Oper_1);
  end Pack4;

  package body Pack4 is
      procedure Oper_1 (X : in out Pack1.Root'Class) is
      begin
          Pack1.Oper_1 (X);
      end Oper_1;
  end Pack4;

Obviously, this extra routine adds additional junk to maintain and an additional
source of errors. And it's weird that an implicit subprogram can be built if
no name is given here, but giving an explicit name loses this option.

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

From: Tucker Taft
Date: Friday, October 24, 2008  9:00 PM

I would be more sympathetic to making the explicit parameter work than making
the rename work.  I would think the adjustment to the wording to make the
explicit parameter work might not be too horrendous.

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

Questions? Ask the ACAA Technical Agent