Version 1.1 of ai22s/ai22-0012-1.txt

Unformatted version of ai22s/ai22-0012-1.txt version 1.1
Other versions for file ai22s/ai22-0012-1.txt

!standard 6.1.1(18.2/5)          21-11-12 AI22-0012-1/00
!class binding interpretation 21-11-12
!status work item 21-11-12
!status received 21-07-07
!priority Medium
!difficulty Hard
!qualifier Error
!subject Incompatibility with AI12-0412-1
!summary
** Tucker is promising a full write-up by Monday; I'll post it as soon
as possible. **
!question
!recommendation
(See Summary.)
!wording
!discussion
!ACATS test
!appendix

From: Tucker Taft
Sent: Wednesday, July 7, 2021  12:45 PM

I believe we missed an incompatibility with AI12-0412-1.  Our goal was to 
allow an abstract class-wide pre/post on a non-abstract function, presuming
that the abstract pre/post functions would be overridden in a descendant.  
Unfortunately, I believe we might have created an incompatibility for a case
where we have an abstract type with a nonabstract primitive, with
*nonabstract* class-wide pre/post.  AI12-0412-1 made it illegal to call such
a subprogram using a non-dispatching call, if the class-wide pre/post was
*nonstatic*.  In Ada 2012, I believe calling such a subprogram was legal.

For example, if we declare an abstract type T0 with a nonabstract primitive 
Foo, with a nonabstract Pre'Class invoking All_Good:

   package P is
        type T0 is abstract tagged private;
        procedure Foo(X : T0) with Pre'Class => All_Good(X);

        function All_Good(X : T0) return Boolean;
   private
       ...
   end P;

We then derive another type T1 from T0, and override the Foo primitive to call
the primitive of its parent type, and then do something more:

   with P;
   package P1 is
         type T1 is new T0 with private;

         procedure Foo(X : T1);
   private
        ...
   end P1;

   package body P1 is
         procedure Foo(X : T1) is
         begin
              P.Foo(T0(X));
              ...
         end Foo;
   end P1;

As far as I can tell, this was legal in Ada 2012, but would be illegal in Ada 
2022 because of AI12-0412-1, which says, in RM 6.1.1(18.2/5):

  If the primitive subprogram S is not abstract, but the given descendant of T 
  is abstract, then a nondispatching call on S is illegal if any Pre'Class or 
  Post'Class aspect that applies to S is other than a static boolean
  expression. Similarly, a primitive subprogram of an abstract type T, to
  which a non-static Pre'Class or Post'Class aspect applies, shall neither
  be the prefix of an Access attribute_reference, nor shall it be a generic
  actual subprogram for a formal subprogram declared by a
  formal_concrete_subprogram_declaration.

Note the use of "static" rather than "nonabstract" in the above paragraph.  I 
think we thought this was a corner case, so we went with the easier rule.  But
we have a customer who already bumped into this apparent incompatibility.

I think the wording should probably be modified as follows:

  If the primitive subprogram S is not abstract, but the given descendant of T
  is abstract, then a nondispatching call on S is illegal if {the
  corresponding expression for} any Pre'Class or Post'Class aspect that applies
  to S [is other than a static boolean expression]{would resolve to include an
  invocation of an abstract function}. Similarly, a primitive subprogram of an
  abstract type T, to which [a non-static]{such a} Pre'Class or Post'Class
  aspect applies, shall neither be the prefix of an Access attribute_reference,
  nor shall it be a generic actual subprogram for a formal subprogram declared
  by a formal_concrete_subprogram_declaration.

Groan...

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

Questions? Ask the ACAA Technical Agent