CVS difference for ai12s/ai12-0412-1.txt

Differences between 1.2 and version 1.3
Log of other versions for file ai12s/ai12-0412-1.txt

--- ai12s/ai12-0412-1.txt	2020/12/04 07:59:30	1.2
+++ ai12s/ai12-0412-1.txt	2021/01/05 04:47:04	1.3
@@ -1,16 +1,16 @@
-!standard 6.1.1(18.2/4)                                    20-12-03  AI12-0412-1/01
+!standard 6.1.1(18.2/4)                                    21-01-03  AI12-0412-1/02
 !class binding interpretation 20-12-03
 !status work item 20-12-03
 !status received 20-11-23
 !priority Low
 !difficulty Easy
 !qualifier Error
-!subject Pre'Class using an abstract function applied to a concrete operation of abstract type 
+!subject Abstract Pre/Post'Class on primitive of abstract type
 !summary
 
 Allow specifying a Pre'Class or Post'Class aspect for a concrete primitive of
-an abstract type even if it uses an abstract function, but then disallow 
-nondispatching calls on such a primitive.
+an abstract type even if it uses an abstract function, but then disallow
+other uses of such a primitive.
 
 !question
 
@@ -32,60 +32,71 @@
 
 ---
 
-Currently the above example is illegal, because the "corresponding expression" 
-for the given Pre'Class aspect, when constructed according to the rules of 
-6.1.1(18/5-18.2/4), would be illegal, since it would involve a call on an 
-abstract function Is_Valid. But the above combination of a null concrete 
-primitive and an abstract Pre'Class would seem quite reasonable.  
+Currently the above example is illegal, because the "corresponding expression"
+for the given Pre'Class aspect, when constructed according to the rules of
+6.1.1(18/5-18.2/4), would be illegal, since it would involve a call on an
+abstract function Is_Valid. But the above combination of a null concrete
+primitive and an abstract Pre'Class would seem quite reasonable.
 
-Should the above be legal? (Yes)
+Should the above be legal? (Yes.)
 
-Note that if this is made legal, then a non dispatching call on the concrete 
-primitive with such a Pre'Class should be caught:
+Note that if this is made legal, then non-dispatching uses of the concrete
+primitive with such an abstract Pre'Class (or Post'Class) should be illegal:
 
   Y : T'Class := ...
 begin
   Do_Stuff (T(Y));
 
-The above call would need to be be illegal, given that we are making a 
-non-dispatching call on Do_Stuff, and it has a Pre'Class that is abstract for 
-the type T.
+The above call would need to be be illegal, given that we are making a
+non-dispatching call on Do_Stuff, and it has a Pre'Class that is abstract for
+the type T. Similarly, passing as a generic formal subprogram or using
+'Access will need to be disallowed.
 
 !recommendation
 
-Using an abstract function in a Pre'Class aspect for an operation of an 
-abstract type is a common pattern. It is inevitable for interface types
-(since all primitive functions of an interface type are necessarily abstract
--- allowed), and will be common for any abstract root
-type. It will also be common to have null defaults for primitives of an 
-abstract type, if they represent a kind of "hook" which is expected to often
-be a no-op. Using these two together, namely a null default and an abstract
-Pre'Class, should be allowed. 
+Using an abstract function in a Pre'Class or a Post'Class aspect for an
+operation of an abstract type is a common pattern. It is inevitable for
+interface types (since all primitive functions of an interface type are
+necessarily abstract -- no "null" functions are allowed), and will be
+common for any abstract root type. It will also be common to have null
+defaults for primitives of an abstract type, if they represent a kind of
+"hook" which is expected to often be a no-op. Using these two together,
+namely a null default and an abstract Pre'Class or Post'Class, should be
+allowed.
 
-As mentioned above, the above combination of features is disallowed by 
+As mentioned above, the above combination of features is disallowed by
 6.1.1(18/5-18.2/4). We propose to allow it, because it would be unfortunate
 to have to provide a concrete Is_Valid for such an abstract type, as then you
-would lose the protection against forgetting to override Is_Valid in a 
+would lose the protection against forgetting to override Is_Valid in a
 concrete descendant. But because it is possible to actually invoke a concrete
-primitive of an abstract type by an explicit conversion to the abstract type, 
+primitive of an abstract type by an explicit conversion to the abstract type,
 we need to catch this problem somewhere. We therefore propose to require that
-it be caught at the point of such a call. Also, we recommend that it be
-illegal even if precondition checks are disabled, as we don't want legality 
-to be affected by the state of an assertion policy.
+it be caught at the point of such a call (or other non-dispatching use). Also,
+we recommend that it be illegal even if corresponding checks are disabled,
+as we don't want legality to be affected by the state of an assertion policy.
 
 Revise 6.1.1(18.2/4):
 
-  The primitive subprogram S is illegal if [it]{the given descendant of T} is 
-  not abstract and the corresponding expression for a Pre'Class or Post'Class 
-  aspect would be illegal. {If S itself is not abstract, then a non 
-  dispatching call on S is illegal if the corresponding expression for a 
-  Pre'Class or Post'Class aspect would be illegal.}
+  The primitive subprogram S is illegal if [it]{the given descendant of
+  T} is not abstract and the corresponding expression for a Pre'Class or
+  Post'Class aspect would be illegal. {If S itself is not abstract, then
+  a non dispatching call on S is illegal if the corresponding expression
+  for a Pre'Class or Post'Class aspect would be illegal.  Similarly, a
+  subprogram S with such a Pre'Class or Post'Class aspect shall not be
+  the prefix of an Access attribute_reference, nor shall it be a generic
+  actual subprogram unless the generic formal subprogram is declared by
+  a formal_abstract_subprogram_declaration.}
 
 !discussion
 
-Most of the rationale is given in the !recommendation. To minimize disruption, 
-we have chosen to keep the changes as part of the existing Static Semantics 
-paragraph (18.2/4), rather than moving them into the Legality Rules paragraphs.
+Most of the rationale is given in the !recommendation. To minimize
+disruption, we have chosen to keep the changes as part of the existing
+Static Semantics paragraph (18.2/4), rather than moving them into the
+Legality Rules paragraphs. The restrictions imposed are essentially
+those associated with abstract subprograms. Effectively the subprogram
+is treated as though it is abstract, except as far as the requirement to
+be overridden, so it can provide a default when inherited by a
+non-abstract type, but not be used directly.
 
 !ASIS
 
@@ -101,12 +112,12 @@
 From: Tucker Taft
 Sent: Monday, November 23, 2020  8:39 AM
 
-!Subject Pre'Class using an abstract function applied to a concrete operation of abstract type 
+!Subject Pre'Class using an abstract function applied to a concrete operation of abstract type
 
 !summary
 
-Allow specifying a Pre'Class or Post'Class aspect for a concrete primitive 
-of an abstract type even if it uses an abstract function, but then disallow 
+Allow specifying a Pre'Class or Post'Class aspect for a concrete primitive
+of an abstract type even if it uses an abstract function, but then disallow
 nondispatching calls on such a primitive.
 
 !problem
@@ -129,58 +140,58 @@
 
 ---
 
-Currently the above example is illegal, because the "corresponding expression" 
-for the given Pre'Class aspect, when constructed according to the rules of 
-6.1.1(18/5-18.2/4), would be illegal, since it would involve a call on an 
-abstract function Is_Valid.  But the above combination of a null concrete 
-primitive and an abstract Pre'Class would seem quite reasonable.   Therefore, 
-we suggest that it should be legal, but then a non dispatching call on the 
+Currently the above example is illegal, because the "corresponding expression"
+for the given Pre'Class aspect, when constructed according to the rules of
+6.1.1(18/5-18.2/4), would be illegal, since it would involve a call on an
+abstract function Is_Valid.  But the above combination of a null concrete
+primitive and an abstract Pre'Class would seem quite reasonable.   Therefore,
+we suggest that it should be legal, but then a non dispatching call on the
 concrete primitive with such a Pre'Clss should be caught:
 
    Y : T'Class := ...
 begin
    Do_Stuff (T(Y));
 
-The above call would need to be be illegal, given that we are making a 
-non-dispatching call on Do_Stuff, and it has a Pre'Class that is abstract for 
+The above call would need to be be illegal, given that we are making a
+non-dispatching call on Do_Stuff, and it has a Pre'Class that is abstract for
 the type T.
 
 !proposal
 
-Using an abstract function in a Pre'Class aspect for an operation of an 
-abstract type is a common pattern.  It is inevitable for interface types 
+Using an abstract function in a Pre'Class aspect for an operation of an
+abstract type is a common pattern.  It is inevitable for interface types
 (since all primitive functions of an interface type are necessarily abstract
 -- no "null" functions are allowed), and will be common for any abstract root
-type.  It will also be common to have null defaults for primitives of an 
-abstract type, if they represent a kind of "hook" which is expected to often 
-be a no-op.  Using these two together, namely a null default and an abstract 
-Pre'Class, should be allowed.  
+type.  It will also be common to have null defaults for primitives of an
+abstract type, if they represent a kind of "hook" which is expected to often
+be a no-op.  Using these two together, namely a null default and an abstract
+Pre'Class, should be allowed.
 
-As mentioned above, the above combination of features is disallowed by 
-6.1.1(18/5-18.2/4).  We propose to allow it, because it would be unfortunate 
+As mentioned above, the above combination of features is disallowed by
+6.1.1(18/5-18.2/4).  We propose to allow it, because it would be unfortunate
 to have to provide a concrete Is_Valid for such an abstract type, as then you
-would lose the protection against forgetting to override Is_Valid in a 
-concrete descendant.  But because it is possible to actually invoke a concrete 
-primitive of an abstract type by an explicit conversion to the abstract type, 
+would lose the protection against forgetting to override Is_Valid in a
+concrete descendant.  But because it is possible to actually invoke a concrete
+primitive of an abstract type by an explicit conversion to the abstract type,
 we need to catch this problem somewhere.  We therefore propose to require that
-it be caught at the point of such a call.  Also, we recommend that it be 
-illegal even if precondition checks are disabled, as we don't want legality 
+it be caught at the point of such a call.  Also, we recommend that it be
+illegal even if precondition checks are disabled, as we don't want legality
 to be affected by the state of an assertion policy.
 
 !wording
 
 Revise 6.1.1(18.2/4):
 
-   The primitive subprogram S is illegal if [it]{the given descendant of T} is 
-   not abstract and the corresponding expression for a Pre'Class or Post'Class 
-   aspect would be illegal.  {If S itself is not abstract, then a non 
-   dispatching call on S is illegal if the corresponding expression for a 
+   The primitive subprogram S is illegal if [it]{the given descendant of T} is
+   not abstract and the corresponding expression for a Pre'Class or Post'Class
+   aspect would be illegal.  {If S itself is not abstract, then a non
+   dispatching call on S is illegal if the corresponding expression for a
    Pre'Class or Post'Class aspect would be illegal.}
 
 !discussion
 
-Most of the rationale is given in the !proposal.  To minimize disruption, we 
-have chosen to keep the changes as part of the existing Static Semantics 
+Most of the rationale is given in the !proposal.  To minimize disruption, we
+have chosen to keep the changes as part of the existing Static Semantics
 paragraph (18.2/4), rather than moving them into the Legality Rules paragraphs.
 
 ****************************************************************
@@ -188,13 +199,13 @@
 From: Claire Dross
 Sent: Thursday, December 3, 2020  9:13 AM
 
-> The above call would need to be be illegal, given that we are making a 
-> non-dispatching call on Do_Stuff, and it has a Pre'Class that is abstract 
+> The above call would need to be be illegal, given that we are making a
+> non-dispatching call on Do_Stuff, and it has a Pre'Class that is abstract
 > for the type T.
 
-I am not sure the use case is important enough to warrant a special case. If 
-Do_Stuff is abstract, then it would be legal I suppose. I am not convinced 
-that it brings much to allow Do_Stuff to be concrete if we are not allowed 
+I am not sure the use case is important enough to warrant a special case. If
+Do_Stuff is abstract, then it would be legal I suppose. I am not convinced
+that it brings much to allow Do_Stuff to be concrete if we are not allowed
 to call it in a non dispatching way.
 
 ****************************************************************
@@ -202,10 +213,10 @@
 From: Randy Brukardt
 Sent: Thursday, December 3, 2020  11:20 PM
 
-I originally had the same thought, but then I remembered that interfaces only 
-allow abstract subprograms and null procedures. If you want to define a 
+I originally had the same thought, but then I remembered that interfaces only
+allow abstract subprograms and null procedures. If you want to define a
 Pre'Class or Post'Class for such a null procedure, you'd run into this problem
-as the functions that you'd call are going to be abstract. Tucker probably 
+as the functions that you'd call are going to be abstract. Tucker probably
 should have put the reason into his original message; he did mention it in his
 AI write-up.
 
@@ -213,10 +224,94 @@
 interface. We should have allowed expression functions to be used that way as
 well (but they hadn't been invented yet).
 
-In any case, we don't want to force people to have to chose between contracts 
+In any case, we don't want to force people to have to chose between contracts
 or default implementations. Ideally, as many features as possible work together
-seamlessly. (If you are like me and don't find interfaces very valuable, then 
+seamlessly. (If you are like me and don't find interfaces very valuable, then
 it's harder to get interested in this fix. But I don't see much point in making
 things harder for those that do like these things.)
+
+****************************************************************
+
+From: Claire Dross
+Sent: Thursday, December 3, 2020  11:20 PM
+
+> I originally had the same thought, but then I remembered that interfaces
+> only allow abstract subprograms and null procedures. If you want to define a
+> Pre'Class or Post'Class for such a null procedure, you'd run into this
+> problem as the functions that you'd call are going to be abstract. Tucker
+> probably should have put the reason into his original message; he did
+> mention it in his AI write-up.
+
+> Remember that a null procedure is essentially a default implementation for
+> an interface. We should have allowed expression functions to be used that
+> way as well (but they hadn't been invented yet).
+
+yes, probably. We already discussed allowing expression functions as default
+of generic units too. I think it would be worthwhile.
+
+> In any case, we don't want to force people to have to chose between
+> contracts or default implementations. Ideally, as many features as possible
+> work together seamlessly.
+
+No, but it could make sense that a subprogram with a default has a contract
+containing only subprograms which have a default.
+
+>(If you are like me and don't find interfaces very
+>valuable, then it's harder to get interested in this fix. But I don't see
+>much point in making things harder for those that do like these things.)
+
+Yes, except it makes the rules harder to understand, so I am still not in
+favor of it. The lengthy discussion about whether or not the initial example
+is legal shows in my opinion that the rules are already far too complex. I
+don't think making them even more complicated is a good idea.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, December 16, 2020  11:33 PM
+
+...
+>>We should have allowed expression functions to be used that
+way as well (but they hadn't been invented yet).
+>
+>yes, probably. We already discussed allowing expression functions as
+>default of generic units too. I think it would be worthwhile.
+
+I'm not sure who "we" are, but both of these ideas have been part of
+expression functions from the very beginning. My original detailed proposal
+for "expression renaming" (which eventually became expression functions)
+ends: [see the !appendix of AI05-0177-1, message of Thursday, March 19, 2009
+12:01 AM]
+
+   Finally, this construct could be allowed as a primitive subprogram of an
+   interface. If we did that, we would get the benefit of the identity
+   function idea without adding anything special specifically for that
+   case. (If we wanted to add the generic default for that case, then it
+   gets a bit messier, but not a huge amount.) We would have to somehow
+   include the expression in the matching rules in order to deal with the
+   Steve Baird problem for diamond inheritance with interfaces. I'm not
+   quite sure this is worth it, but it does add to the things that you
+   cannot do now.
+
+I think we eventually dropped these ideas in the interest of simplification.
+I know I was focused on getting expression functions into the language, and
+a simpler proposal certainly made that easier.
+
+I'm pretty sure that I wrote up a more detailed proposal for rules for these
+two extensions to expression functions, but I haven't been able to find it.
+Probably it never made it to an AI and was buried somewhere in the pile of
+e-mail related to Ada 2012 (or perhaps in one of the phone meetings minutes
+-- those were never put on-line and thus cannot be searched -- much of the
+Ada 2012 design was decided in those meetings).
+
+Anyway, I don't know why this idea wasn't re-raised for Ada 202x, but it's
+obviously too late now.
+
+****************************************************************
+
+From: Claire Dross
+Sent: Thursday, December 17, 2020  2:45 AM
+
+Yes, let's reraise it for Ada 202y.
 
 ****************************************************************

Questions? Ask the ACAA Technical Agent