CVS difference for ai12s/ai12-0075-1.txt
--- ai12s/ai12-0075-1.txt 2015/11/24 02:38:31 1.5
+++ ai12s/ai12-0075-1.txt 2017/10/12 04:36:52 1.6
@@ -466,3 +466,592 @@
address the original compatibility issue that Steve himself raised - Editor.]
****************************************************************
+
+From: Steve Baird
+Sent: Thursday, October 5, 2017 2:55 PM
+
+It seems clear that compatibility issues are a major concern associated with
+this proposal.
+
+We don't want examples which were previously legal to start running afoul of
+the "no check failures in a static expression" rule.
+
+Bob suggested one solution to this problem: an expression which fails the
+"no check failures" test becomes non-static, as opposed to illegal.
+
+But the consensus in Vienna (I am told) was that we also don't want to start
+allowing constructs which were previously illegal.
+
+There is a solution which satisfies both constraints, although I am not
+claiming that it is elegant: we relax the legality rules as per Bob's proposal
+but only in the case of a static expression that includes a call to an
+expression function. Such an expression could never currently be static, so
+this relaxation would not cause us to accept something that was previously
+rejected.
+
+So we would continue to disallow
+
+ N : constant := 0;
+ begin
+ if N /= 0 then
+ X := 10 / N;
+ end if;
+
+but we would also continue to allow
+
+ N : constant := 0;
+ function Ratio (X : Integer) return Integer is (X / N);
+ begin
+ if N /= 0 then
+ X := Ratio (10);
+ end if;
+
+====
+
+I was tasked with assessing the compatibility impact of an earlier version of
+this proposal, trying to somehow figure out how often situations like
+
+ procedure Foo is
+ function Inc (X : integer) return Integer is (X + 1);
+ subtype S is Integer range 0 .. Inc (3);
+ Y : S := ... ;
+ begin
+ -- if S is a static subtype then this case stmt is illegal
+ case Y is
+ when 0 .. 33 => ...;
+ when 44 .. 55 => ...;
+ when others => ... ;
+ end case;
+ end;
+
+arise in practice. I didn't get this done.
+
+====
+
+There is the point mentioned in the !discussion section of this AI:
+
+ 3) Do we need to say anything about type invariants? No,
+ because if a function has a parameter (or result) of a private type,
+ then it's not a static function. But what if it is completed as
+ a static expression function after the private type is completed?
+ Maybe we need a rule saying that if a type invariant applies to
+ a function than the function is not a static expression function
+ (like the rule already given for predicates).
+
+I think we do need this rule.
+
+The AI says
+ A "static expression function" is defined to be an expression function
+ - ...; and
+ - ...; and
+ - ...; and
+ - ...; and
+ - ...
+
+I think we need to invent a term for the property implicitly defined in the
+section on type invariants
+ An invariant is checked upon successful return from any
+ call on a subprogram or entry that ...
+
+Something like
+ An entry or subprogram is said to be an "invariant
+ boundary" entry or subprogram if ...
+
+followed by a use of the new term
+
+ An invariant is check upon successful return from any
+ call on an invariant boundary subprogram or entry.
+
+Then we can use the new term to add a new clause to the definition of "static
+expression function" along the lines of
+ "which is not an invariant boundary subprogram; and"
+
+Other possible names for the new term: "invariant enforcing", "invariant
+checking".
+
+====
+
+Opinions?
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, October 5, 2017 3:16 PM
+
+> It seems clear that compatibility issues are a major concern
+> associated with this proposal.
+
+Maybe for some folks. Expression functions are pretty new!
+
+...
+> There is a solution which satisfies both constraints, although I am
+> not claiming that it is elegant: we relax the legality rules as per
+> Bob's proposal but only in the case of a static expression that
+> includes a call to an expression function. Such an expression could
+> never currently be static, so this relaxation would not cause us to
+> accept something that was previously rejected.
+
+That seems fine to me.
+
+> ...
+> I think we need to invent a term for the property implicitly defined
+> in the section on type invariants
+> An invariant is checked upon successful return from any
+> call on a subprogram or entry that ...
+>
+> Something like
+> An entry or subprogram is said to be an "invariant
+> boundary" entry or subprogram if ...
+
+I would somewhat rather associate the notion of boundary with the type being
+defined, rather than this one particular aspect that is checked at the
+boundary. Perhaps simply "boundary subprogram for private type T" or
+"boundary subprogram for some partial view." Getting the word invariant there
+muddies the waters a bit for me. The concept of such a boundary exists even
+if no invariants have been defined explicitly.
+
+I suppose any term we pick would eventually grow on me... ;-)
+
+...
+> Other possible names for the new term: "invariant enforcing",
+> "invariant checking".
+
+I find these names even muddier... I would like to describe the concept,
+without talking about what things might happen when crossing that border.
+Sort of like calling the border between two countries an "immigration control
+line."
+
+> ====
+>
+> Opinions?
+
+See above.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Thursday, October 5, 2017 3:41 PM
+
+> I would somewhat rather associate the notion of boundary with the
+> type being defined,
+I like that idea too.
+
+IIRC, we have wanted a well-defined term for this for other reasons in the
+past.
+
+Would precisely defining the boundary for a type also help with the questions
+raised in AI12-0210 (Type Invariants and Generics)?
+
+It seems to me that the two issues are related.
+
+Roughly speaking, the idea we are trying to capture here is that a boundary
+subprogram for a given private type
+ a) can see the implementation of the private type; and
+ b) is callable from places that cannot see the implementation
+ of the private type; and
+ c) has a non-in-mode parameter or a function result of the type.
+
+Right?
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, October 5, 2017 3:46 PM
+
+> > It seems clear that compatibility issues are a major concern
+> > associated with this proposal.
+>
+> Maybe for some folks. Expression functions are pretty new!
+
+Two points on this:
+
+(1) My experience is that once one has expression functions and is used to
+the idea, one tends to write everything possible as an expression function.
+(This is a problem if you are writing Ada 2005 ACATS tests or for a compiler
+that doesn't support them. I've done both. :-)
+
+(2) This compatibility problem exists any time a regular function is changed
+into an expression function or vice-versa. It's not just a one time thing.
+
+In particular, I expect Janus/Ada customers to rewrite regular functions into
+expression functions in some cases, because Janus/Ada only supports inlining
+on expression functions. When that is done, they'd be at risk of running into
+these compatibility issues. [Note to any Janus/Ada customers reading this: I'm
+speaking in the future tense here. :-)]
+
+...
+> > There is a solution which satisfies both constraints, although I am
+> > not claiming that it is elegant: we relax the legality rules as per
+> > Bob's proposal but only in the case of a static expression that
+> > includes a call to an expression function. Such an expression could
+> > never currently be static, so this relaxation would not cause us to
+> > accept something that was previously rejected.
+>
+> That seems fine to me.
+
+Cool. I predicted to Steve the opposite. (It is a rather clunky rule, and I
+thought you'd object to the "bolted-on" look of it.)
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, October 5, 2017 6:42 PM
+
+> Roughly speaking, the idea we are trying to capture here is that a
+> boundary subprogram for a given private type
+> a) can see the implementation of the private type; and
+> b) is callable from places that cannot see the implementation
+> of the private type; and
+> c) has a non-in-mode parameter or a function result of the type.
+
+I don't understand why you have that last bullet in that form. Why does the
+mode matter? And are you considering access parameters or access results?
+From a SPARK point of view, you will still be presuming the invariant is true
+on entry, which you will not be doing for local functions.
+
+> Right?
+
+Modulo my complaint about (c)
+
+****************************************************************
+
+From: Steve Baird
+Sent: Thursday, October 5, 2017 7:08 PM
+
+> I don't understand why you have that last bullet in that form. Why does the
+> mode matter? And are you considering access parameters or access results?
+> From a SPARK point of view, you will still be presuming the invariant is true
+> on entry, which you will not be doing for local functions.
+
+Good point about access parameters.
+
+And even for others, I see your point.
+
+There are advantages to ignoring the parameter mode completely (as opposed to
+special rules for in-mode non-access parameters) and I don't see any
+disadvantages, even if no runtime check is performed in that case.
+
+And of course when I talked about a parameter/result of the private type, I
+should have been talking about a parameter/result of a type that has a part
+which is of that type.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, October 5, 2017 8:05 PM
+
+> Good point about access parameters.
+>
+> And even for others, I see your point.
+>
+> There are advantages to ignoring the parameter mode completely (as
+> opposed to special rules for in-mode non-access parameters) and I
+> don't see any disadvantages, even if no runtime check is performed in
+> that case.
+
+Right. This is another reason I would be reluctant to include the word
+"invariant" in the term we end up using.
+
+> And of course when I talked about a parameter/result of the private
+> type, I should have been talking about a parameter/result of a type
+> that has a part which is of that type.
+
+You could argue that boundary subprograms need not have any parameters or
+results of the type. The key point is that their body has more visibility
+on the type than their callers. They might be passed an access value and
+follow it three steps to an object of the private type, and do their thing
+there. SPARK as of today (prior to "safe" pointers) doesn't have this
+problem, but presumably in Ada we do have that situation, and SPARK with
+safe pointers might have it as well. So I think the parameter profile might
+be irrelevant once you start having pointers.
+
+But now if we bring this back to expression functions -- can they be static
+if they have any parameters of an access type? And I have lost track of what
+this whole thing was about -- why are invariant checks a problem? We don't
+want to do them as part of static evaluation? Why don't we say that a static
+expression function must not be the completion of a function declaration.
+Hence, if you want a function to be static, give the expression when it is
+declared.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, October 5, 2017 8:21 PM
+
+...
+> But now if we bring this back to expression functions -- can they be
+> static if they have any parameters of an access type?
+> And I have lost track of what this whole thing was about -- why are
+> invariant checks a problem?
+
+From memory, we don't want any checks that might fail in a static function
+call. We disallow predicates, and Steve decided we needed to do the same
+for any invariant checks.
+
+Making the function visible without a completion doesn't completely
+eliminate the problem, as an invariant can be visibly defined and so can
+an expression function of a private type.
+
+Moreover, I already strongly dislike the fact that the implementation of a
+static function has to be exposed. It makes them go contrary to the basic
+point of Ada (a strong separation between specification and implementation).
+Making that problem worse doesn't improve the AI in my view.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, October 5, 2017 9:43 PM
+
+This surprises me. What is the purpose of a static function if you don't
+know it is static and cannot use it as one? At least with this AI, the only
+way you know that an expression function is a static function is by looking
+at its defining expression. I suppose if there were an aspect "Static" or
+equivalent, then you could postpone the "body" of the expression function to
+the private part. Am I missing something?
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, October 5, 2017 10:01 PM
+
+> This surprises me. What is the purpose of a static function if you
+> don't know it is static and cannot use it as one?
+
+One could argue "approximately the same as any other user-defined static
+function", but that's a discussion for a different time.
+
+... > At least with this AI, the only way you know that an expression
+> function is a static function is by looking at its defining
+> expression. I suppose if there were an aspect "Static" or equivalent,
+> then you could postpone the "body" of the expression function to the
+> private part. Am I missing something?
+
+There surely should be a "Static_Possible" aspect, which among other things
+would allow deferring the expression elsewhere (probably not to a body, though,
+as the compiler has to be able to see a static expression that it is
+evaluating). It certainly would be needed should we ever try to expand static
+processing to user-defined static expressions. (Jeff told me privately that
+the UK would like to see static expression processing regularized. I think
+we've already rejected that idea for this cycle, but I think we need to leave
+the possibility open.)
+
+***************************************************************
+
+From: Tucker Taft
+Sent: Thursday, October 5, 2017 10:57 PM
+
+> There surely should be a "Static_Possible" aspect, which among other
+> things would allow deferring the expression elsewhere (probably not to
+> a body, though, as the compiler has to be able to see a static
+> expression that it is evaluating).
+
+I am dubious. Static expressions can affect legality, so you really have to
+know what the function is computing. There really can't be any "abstraction"
+here to speak of.
+
+> It certainly would be needed should we ever try to expand static
+> processing to user-defined static expressions. (Jeff told me privately
+> that the UK would like to see static expression processing
+> regularized. I think we've already rejected that idea for this cycle,
+> but I think we need to leave the possibility open.)
+
+I think you are talking about a completely different AI than this one. Given
+the current AI, there seems no particular value to allowing a static
+expression function to be a completion.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, October 5, 2017 11:11 PM
+
+...
+> I think you are talking about a completely different AI than this one.
+> Given the current AI, there seems no particular value to allowing a
+> static expression function to be a completion.
+
+Yes, a different (and future) AI. But I don't want this AI to prevent that AI
+from being possible.
+
+***************************************************************
+
+From: Tucker Taft
+Sent: Thursday, October 5, 2017 11:04 PM
+
+> Yes, a different (and future) AI. But I don't want this AI to prevent
+> that AI from being possible.
+
+Right. But being *more* restrictive than absolutely necessary is our usual
+approach. By requiring static expression functions to be defined where they
+are declared, we are keeping this AI simpler, and allowing ourselves to relax
+the restrictions later.
+
+***************************************************************
+
+From: Steve Baird
+Sent: Thursday, October 5, 2017 11:09 PM
+
+> And I have lost track of what this whole thing was about -- why are
+> invariant checks a problem? We don't want to do them as part of static
+> evaluation?
+
+Exactly.
+
+> Why don't we say that a static expression function must not be the
+> completion of a function declaration.
+
+Sounds like a nice clean solution; I like it.
+
+It is inconsistent with our treatment of deferred constants (because a use of
+a deferred constant can be static if the completion is visible), but that's ok
+I suppose.
+
+***************************************************************
+
+From: Steve Baird
+Sent: Friday, October 6, 2017 11:26 AM
+
+> It is inconsistent with our treatment of deferred constants (because a
+> use of a deferred constant can be static if the completion is
+> visible),
+
+Do we decide whether an expression function is a static expression function
+when the function is declared or when it is used?
+
+Consider:
+
+ package Pkg is
+ type T is private;
+ Dc : constant T;
+ function Expr_Func return T is (Dc);
+ private
+ type T is new Integer;
+ Dc : constant T := 0;
+ Named_Number : constant := Expr_Func; -- legal?
+ end;
+
+***************************************************************
+
+From: Randy Brukardt
+Sent: Monday, October 9, 2017 7:07 PM
+
+>> There surely should be a "Static_Possible" aspect, which among other
+>> things would allow deferring the expression elsewhere (probably not
+>> to a body, though, as the compiler has to be able to see a static
+>> expression that it is evaluating).
+
+>I am dubious. Static expressions can affect legality, so you really
+>have to know what the function is computing. There really can't be any
+>"abstraction" here to speak of.
+
+The only reason to write a static function in the first place is to provide
+some "abstraction". Else it is just useless complication for the reader. If
+you are right here, then there shouldn't be any static functions to begin
+with.
+
+...
+> >>> It certainly would be needed should we ever try to expand static
+> >>> processing to user-defined static expressions. (Jeff told me
+> >>> privately that the UK would like to see static expression
+> >>> processing regularized. I think we've already rejected that idea
+> >>> for this cycle, but I think we need to leave the possibility
+> >>> open.)
+> >>
+> >> I think you are talking about a completely different AI than this
+> >> one. Given the current AI, there seems no particular value to
+> >> allowing a static expression function to be a completion.
+> >
+> > Yes, a different (and future) AI. But I don't want this AI to
+> > prevent that AI from being possible.
+>
+> Right. But being *more* restrictive than absolutely necessary is our
+> usual approach. By requiring static expression functions to be
+> defined where they are declared, we are keeping this AI simpler, and
+> allowing ourselves to relax the restrictions later.
+
+Such a future AI would have to have a way (almost certainly an aspect) to mark
+completions that are static functions. (A "generalization" proposal that
+doesn't support private types is not really fixing anything, IMHO.) An AI that
+has some sort of automatic static functions is going to conflict with that
+future AI, as there would be a mismash of automatic and declared static
+functions, and probably conflicts in some cases. Automatic static functions
+is a dead-end that would pretty much prevent any further changes to static
+processing.
+
+***************************************************************
+
+From: Tucker Taft
+Sent: Monday, October 9, 2017 8:45 PM
+
+>> Right. But being *more* restrictive than absolutely necessary is our
+>> usual approach. By requiring static expression functions to be
+>> defined where they are declared, we are keeping this AI simpler, and
+>> allowing ourselves to relax the restrictions later.
+>
+> Such a future AI would have to have a way (almost certainly an aspect)
+> to mark completions that are static functions. (A "generalization"
+> proposal that doesn't support private types is not really fixing
+> anything, IMHO.) An AI that has some sort of automatic static
+> functions is going to conflict with that future AI, as there would be
+> a mismash of automatic and declared static functions, and probably
+> conflicts in some cases. Automatic static functions is a dead-end that
+> would pretty much prevent any further changes to static processing.
+
+I could see adding an aspect to claim that something is a static function,
+and the compiler would check to be sure the expression then and there. We
+could provide a configuration pragma some day to make it automatic, I suppose.
+
+But I still don't get how you can complete a static function in a private part
+or a body, if it is going to be static outside the package as well. Because
+the *values* returned by the function can really matter to the caller, as they
+determine legality, and in some weird cases, can even determine the type (e.g.
+A'First(N) where "N" is a static expression function).
+
+Are you proposing that inside the package the function can be static, but not
+outside? I suppose I could see some value in that. I think that is how
+deferred constants work. But I was getting the impression you wanted the
+"I_Am_Static" aspect on the visible declaration of the function, but not
+provide the body there as well. That is what I don't understand...
+
+***************************************************************
+
+From: Randy Brukardt
+Sent: Monday, October 9, 2017 9:21 PM
+
+...
+> But I still don't get how you can complete a static function in a
+> private part or a body, if it is going to be static outside the
+> package as well. Because the *values* returned by the function can
+> really matter to the caller, as they determine legality, and in some
+> weird cases, can even determine the type (e.g. A'First(N) where "N" is
+> a static expression function).
+
+I don't get this obsession with values. The first thing an Ada programmer
+learns is to use names rather than literals. And I have to assume the desire
+to use expression functions in static expressions is to get more abstraction
+into the expression.
+
+Yes, the value can determine legality. But so what? If the function implements
+a sensible, well-documented abstraction, it will work fine without worrying
+about the exact value returned. If it doesn't, well, we can't legislate
+perfection. I doubt very much that you care about the values of expressions in
+your program unless the compiler rejects them. That certainly would be the
+case here.
+
+> But I was getting the impression you wanted the "I_Am_Static"
+> aspect on the visible declaration of the function, but not provide the
+> body there as well. That is what I don't understand...
+
+What about "abstraction" do you not understand?? Why you think these functions
+are somehow different than any other function ever written is what I don't
+understand. Any function someone writes might return a value other than one
+expected. Whether that makes the program illegal or just raises an exception
+doesn't change the response to it much. The programmer then has to look at the
+function body to see why an incorrect value was returned -- but that's the
+only time that one would look at the function body.
+
+If static expression functions aren't going to be used to provide abstraction,
+what else could they possibly be good for?? As I previously said, if they
+don't provide abstraction, then they aren't providing anything at all, and we
+should simply forget this idea.
+
+***************************************************************
Questions? Ask the ACAA Technical Agent