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

Differences between 1.7 and version 1.8
Log of other versions for file ai12s/ai12-0236-1.txt

--- ai12s/ai12-0236-1.txt	2019/01/16 00:47:58	1.7
+++ ai12s/ai12-0236-1.txt	2019/01/18 05:09:54	1.8
@@ -1,13 +1,17 @@
-!standard 3.9.2(3)                                    19-01-15  AI12-0236-1/05
+!standard 2.8(6)                                      19-01-17  AI12-0236-1/07
+!standard 3.9.2(3)
 !standard 3.10.2(9.1/3)
 !standard 3.10.2(32.2/3)
 !standard 4.3.2(5.4/3)
 !standard 4.3.3(15.1/3)
+!standard 4.4(7/3)
+!standard 4.5.9(0)
 !standard 6.2(10/4)
-!standard 6.9(0)
+!standard 7.5(2.1/5)
 !standard 8.1(3)
 !class Amendment 17-09-06
 !status Amendment 1-2012 19-01-15
+!status work item 19-01-17
 !status ARG Approved 8-1-3  19-01-14
 !status work item 17-09-06
 !status received 17-06-21
@@ -17,7 +21,7 @@
 !summary
 
 Add a new kind of expression, the declare expression, that allows one to
-declare local objects and object renamings in an expression context.
+declare local constants and object renamings in an expression context.
 
 !problem
 
@@ -35,15 +39,16 @@
 
    procedure Fgetc (Stream : File_Descr; Result : out Int) with
      Post =>
-       (if The_File (Cur_Position'Old) = EOF_Ch
-        then Cur_Position = Cur_Position'Old
+       (if Stream.The_File (Stream.Cur_Position'Old) = EOF_Ch
+        then Stream.Cur_Position = Stream.Cur_Position'Old
           and then Result = EOF
-        elsif The_File (Cur_Position'Old) = ASCII.LF
-        then Cur_Position = Cur_Position'Old
+        elsif Stream.The_File (Stream.Cur_Position'Old) = ASCII.LF
+        then Stream.Cur_Position = Stream.Cur_Position'Old
           and then Result = Character'Pos (ASCII.LF)
         else
-          Cur_Position = Cur_Position'Old + 1
-          and then Result = Character'Pos (The_File (Cur_Position'Old)));
+          Stream.Cur_Position = Stream.Cur_Position'Old + 1
+          and then Result = 
+             Character'Pos (Stream.The_File (Stream.Cur_Position'Old)));
 
 The contract is not extremely complex in and of itself, but the fact
 that some expressions are repeated makes it more difficult to read - for
@@ -56,29 +61,71 @@
 
 !wording
 
-Add a new section 6.9, following 6.8 "Expression Functions":
+Add a new section 4.5.9, following 4.5.8 "Quantified Expressions":
 
-6.9 Declare Expressions
+4.5.9 Declare Expressions
 
+Declare expressions provide a way to declare local constants and object 
+renamings in an expression context.
+
 Syntax
 
-declare_expression ::= (declare {declare_item} begin *body*_expression)
+declare_expression ::= 
+    declare {declare_item} 
+    begin *body*_expression
 
 declare_item ::= object_declaration | object_renaming_declaration
 
-AARM Rationale: We allow "(declare begin expression)" with no
+AARM Reason: We allow "(declare begin expression)" with no
 declare_items, for uniformity with block statements, which also allow a
 pointless "declare".
 
+Wherever the Syntax Rules allow an expression, a declare_expression may be 
+used in place of the expression, so long as it is immediately surrounded by 
+parentheses.
+
+AARM Discussion: The syntactic category declare_expression appears only as a 
+primary that is parenthesized. The above rule allows it to additionally be 
+used in other contexts where it would be directly surrounded by parentheses.
+This is the same rule that is used for conditional_expressions; see 4.5.7 for
+a detailed discussion of the meaning and effects of this rule. 
+
 Legality Rules
 
 A declare_item that is an object_declaration shall declare a
 constant of a nonlimited type.
 
+  AARM Reason: We disallow limited objects to avoid the horror of 
+  task waiting in the middle of an expression. The solution used for 
+  controlled objects (wait until the entire expression is finished) isn't 
+  appropriate for tasks. This restriction also eliminates build-in-place 
+  complexities and the need to activate tasks found in a declare_item. 
+
+A declare_item that is an object_renaming_declaration (see 8.5.1) shall not 
+rename an object of a limited type that is a function_call, aggregate, a 
+parenthesized expression, qualified_expression, or type_conversion with an 
+operand of one of these, a conditional_expression that has at least one 
+dependent_expression that is one of these, or a declare_expression whose 
+body_expression is one of these.
+
+  AARM Reason: We disallow renaming limited temporary objects (like the result
+  of a function call) for the same reasons as for stand-alone objects.
+  We do allow renaming existing limited objects as these don't cause any
+  problems. Note that one cannot directly rename an aggregate, parenthesized
+  expression, conditional_expression, or declare_expression (these are not 
+  names), but any of these can appear inside of a qualified expression or
+  type conversion (which are names and thus can be renamed).
+
 The following are not allowed within a declare_expression: a declaration
 containing the reserved word 'aliased'; the attribute_designator Access
-or Unchecked_Access; an anonymous access type.
+or Unchecked_Access; or an anonymous access type.
 
+  AARM Reason: We do not want to define accessibility rules for declare_items,
+  as nested declare_expressions cause complexities or usage warts. 
+  We want to keep this feature simple to use, understand, and implement. 
+  Thus, we do not allow any of the features that would require accessibility
+  rules.
+
 Name Resolution Rules
 
 If a declare_expression is expected to be of a type T, then the
@@ -113,45 +160,80 @@
          not Tampering_With_Elements_Prohibited (Result) and then
          not Tampering_With_Cursors_Prohibited (Result) and then
          Result.Capacity >= Length)
+
+[End of new 4.5.9]
 
-[End of new 6.9]
+Modify 2.8(6):
 
-Add after the penultimate sentence of 3.9.2(3):
+  * After a semicolon delimiter, but not within a formal_part{,}[ or]
+    discriminant_part{, or declare_expression.
 
-    A declare_expression is statically, dynamically, or indeterminately
-    tagged according to its *body*_expression.
+Modify 3.9.2(3):
+
+   A name or expression of a tagged type is either statically tagged, 
+   dynamically tagged, or tag indeterminate, according to whether, when used 
+   as a controlling operand, the tag that controls dispatching is determined 
+   statically by the operand's (specific) type, dynamically by its tag at 
+   run time, or from context. A qualified_expression or parenthesized 
+   expression is statically, dynamically, or indeterminately tagged according 
+   to its operand. {A declare_expression is statically, dynamically, or 
+   indeterminately tagged according to its *body*_expression. A 
+   conditional_expression is statically, dynamically, or indeterminately 
+   tagged according to rules given in 4.5.7.} For other kinds of 
+   names and expressions, this is determined as follows:
+
+[Editor's note: This looks like a complete list of exceptions from the usual
+rule, but we previously did not mention the special rules for 
+conditional_expression. We're fixing that now.]
 
 Add after 3.10.2(9.1/3):
 
-    The accessibility level of a declare_expression (see 6.9) is
+    The accessibility level of a declare_expression (see 4.5.9) is
     the accessibility level of the *body*_expression.
 
 Add to the definition of "distributed accessibility" after 3.10.2(32.2/3):
 
-   * a declare_expression (see 6.9); or
+   * a declare_expression (see 4.5.9); or
 
 Add after 4.3.2(5.4/3), in the rule for extension aggregates:
 
-   * a declare_expression whose *body*_expression would violate this
-     rule.
+   * a declare_expression (see 4.5.9) whose *body*_expression would 
+     violate this rule.
 
    [Editor's note: We have to add a semicolon and "nor" to the previous
    bullet, to match the others in this set.]
 
 Adding after 4.3.3(15.1/3): (this allows "others" in *body_*expressions)
 
-        For a declare_expression, the applicable index constraint for
-        the *body*_expression is that, if any, defined for the
+        For a declare_expression (see 4.5.9), the applicable index 
+        constraint for the *body*_expression is that, if any, defined for the
         declare_expression.
 
   [Editor's note: We have to change the period to a semicolon on the previous
    bullet.]
 
+Replace 4.4(7/3) with:
+
+  primary ::=
+     numeric_literal | null | string_literal | aggregate
+   | name | allocator | (expression)
+   | (conditional_expression) | (quantified_expression)
+   | (declare_expression)
+
 Add to the end of 6.2(10/4):
 
     For a declare_expression, this object is the one associated with the
     *body*_expression.
 
+Modify 7.5(2.1/5):
+
+In the following contexts, an expression of a limited type is not permitted 
+unless it is an aggregate, a function_call, a raise_expression, a 
+parenthesized expression or qualified_expression whose operand is permitted 
+by this rule, [or] a conditional_expression all of whose dependent_expressions
+are permitted by this rule{, or a dependent_expression whose body_expression 
+is permitted by this rule}: 
+
 Add after 8.1(3):
 
     - a declare_expression
@@ -171,8 +253,6 @@
 The restriction to nonlimited types is to avoid implementation
 difficulties related to build-in-place and task waiting.
 
-If we allowed limited types, we would probably need to update 7.5(2.1).
-
 A declare expression cannot be static or predicate-static
 (see 4.9 and 3.2.4).
 
@@ -200,18 +280,99 @@
    procedure Fgetc (Stream : File_Descr; Result : out Int) with
      Post =>
        (declare
-          Old_Pos : constant Position := Cur_Position'Old;
-          The_Char : constant Character := The_File (Old_Pos);
-          Pos_Unchg : constant Boolean := Cur_Position = Old_Pos;
+          Old_Pos : constant Position := Stream.Cur_Position'Old;
+          The_Char : constant Character := Stream.The_File (Old_Pos);
+          Pos_Unchg : constant Boolean := Stream.Cur_Position = Old_Pos;
         begin
            (if The_Char = EOF_Ch
               then Pos_Unchg and then Result = EOF
             elsif The_Char = ASCII.LF
               then Pos_Unchg and then Result = Character'Pos (ASCII.LF)
             else
-              Cur_Position = Old_Pos + 1
+              Stream.Cur_Position = Old_Pos + 1
               and then Result = Character'Pos (The_Char)));
 
+!corrigendum 4.4(7/3)
+
+@drepl
+@xcode<@fa<primary>@fa< ::= >
+   @fa<numeric_literal | >@ft<@b<null>>@fa< | string_literal | aggregate>
+ @fa<| name | allocator | (expression)>
+ @fa<| (conditional_expression) | (quantified_expression)>>
+@dby
+@xcode<@fa<primary>@fa< ::= >
+   @fa<numeric_literal | >@ft<@b<null>>@fa< | string_literal | aggregate>
+ @fa<| name | allocator | (expression)>
+ @fa<| (conditional_expression) | (quantified_expression)>
+ @fa<| (declare_expression)>>
+
+!corrigendum 4.5.9(0)
+
+@dinsc
+Declare expressions provide a way to declare local constants and object 
+renamings in an expression context.
+
+@s8<@i<Syntax>>
+
+@xcode<@fa<declare_expression>@fa< ::= >
+    @ft<@b<declare>>@fa< {declare_item} >
+    @ft<@b<begin> @i<body_>>@fa<expression>>
+
+@xcode<@fa<declare_item>@fa< ::= >@fa<object_declaration | object_renaming_declaration>>
+
+Wherever the Syntax Rules allow an @fa<expression>, a @fa<declare_expression>
+may be used in place of the @fa<expression>, so long as it is immediately 
+surrounded by parentheses.
+
+@s8<@i<Legality Rules>>
+
+A @fa<declare_item> that is an @fa<object_declaration> shall declare a
+constant of a nonlimited type. 
+
+A @fa<declare_item> that is an @fa<object_renaming_declaration> (see 8.5.1) shall 
+not rename an object of a limited type that is a @fa<function_call>, @fa<aggregate>,
+a parenthesized expression, @fa<qualified_expression>, or @fa<type_conversion>
+with an operand of one of these, a @fa<conditional_expression> that has at 
+least one @i<dependent_>@fa<expression> that is one of these, or a
+@fa<declare_expression> whose @i<body_>@fa<expression> is one of these.
+
+The following are not allowed within a @fa<declare_expression>: a declaration
+containing the reserved word @b<aliased>; the @fa<attribute_designator> Access
+or Unchecked_Access; or an anonymous access type.
+
+@s8<@i<Name Resolution Rules>>
+
+If a @fa<declare_expression> is expected to be of a type @i<T>, then the
+@i<body_>@fa<expression> is expected to be of type @i<T>. Similarly, if a
+@fa<declare_expression> is expected to be of some class of types, then the
+@i<body_>@fa<expression> is subject to the same expectation. If a 
+@fa<declare_expression> shall resolve to be of a type @i<T>, then the 
+@i<body_>@fa<expression> shall resolve to be of type @i<T>.
+
+The type of a @fa<declare_expression> is the type of the 
+@i<body_>@fa<expression>.
+
+@s8<@i<Dynamic Semantics>>
+
+For the evaluation of a @fa<declare_expression>, the @fa<declare_item>s are
+elaborated in order, and then the @i<body_>@fa<expression> is evaluated. The
+value of the @fa<declare_expression> is that of the @i<body_>@fa<expression>.
+
+@s8<@i<Examples>>
+
+The postcondition for Ada.Containers.Vectors."&" (see A.18.2) could have
+been written:
+
+@xcode<@b<with> Post =@>
+   (@b<declare>
+      Result @b<renames> Vectors."&"'Result;
+      Length : @b<constant> Count_Type := Left.Length + Right.Length;
+    @b<begin>
+      Result.Length = Length @b<and then>
+      @b<not> Tampering_With_Elements_Prohibited (Result) @b<and then>
+      @b<not> Tampering_With_Cursors_Prohibited (Result) @b<and then>
+      Result.Capacity @>= Length)>
+
 !ASIS
 
 New ASIS queries are needed. Those are TBD.
@@ -2610,6 +2771,1153 @@
         (if M > 0 then M > T.C else M < T.D))
 
 is missing the "declare" keyword.
+
+***************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, January 15, 2019  6:46 PM
+
+Here are a number of issues that I've noticed with AI12-0236-1 as I prepare 
+to add it to the draft Standard. I don't think any of these are controversial,
+but since these all but the last two go beyond editorial, I'm asking if anyone
+has an objections to any of these suggestions. Otherwise, I will go ahead and
+add declare_expressions to the Standard as outlined here.
+
+--------
+
+(1) The syntax non-terminal declare_expression is not used anywhere in the AI. 
+I would expect that it should be added to "primary", just like 
+conditional_expression. It certainly has to be added *somewhere* in the 
+expression grammar. Note that conditional_expression is parenthesized as a 
+primary, we'd do the same here. See also item (2), below.
+
+(2) 4.5.7 (conditional expressions) and 4.5.8 (quantified expressions) have 
+rules allowing extra parentheses to be dropped. This AI does not have that 
+rule. This of course ties into the syntax of the use of declare_expression, 
+which is missing from the AI. I intend to add that rule:
+
+Wherever the Syntax Rules allow an expression, a declare_expression may be 
+used in place of the expression, so long as it is immediately surrounded by 
+parentheses.
+
+An alternative to both (1) and (5) would be to follow the model of 
+raise_expression instead. That is a relation, rather than a primary, and does 
+not require parentheses to combine it with boolean operators. However, that 
+would requiring changing to body_simple_expression to avoid ambiguity, and 
+there might be additional issues (I didn't try to figure that out). It also 
+would be unnecessarily different than the conditional_expression model.
+Thus, I stuck with the conditional_expression model.
+
+(3) Way back when, Steve had a insane example of putting a pragma into a 
+declare_expression. I suggested that we not allow that, as pragmas in the 
+middle of expressions seems like asking for trouble. (The definitions of many 
+types of pragmas assume that they occur between entities.) Steve's example 
+showed an example of an Assert pragma in a default expression that has 
+different assertion policies applied. He of course wanted to know if those 
+expressions conformed. Let's not answer questions like that. :-)
+
+The reason it appears to be allowed is the semicolon after the declarations 
+in this syntax. I think that is an accident of the syntax, and the solution 
+is to disallow it explicitly (just as we do in discriminant_parts).
+
+So we need to modify 2.8(6):
+
+* After a semicolon delimiter, but not within a formal_part{,}[ or]
+  discriminant_part{, or declare_expression.
+
+I note that if we decide in the future to allow this sort of thing, we can 
+drop the rule. But if we don't have the rule, then we have to answer every 
+question about pragmas in expressions that someone can dream up. (Pragma 
+Suppress in a declare_expression, anyone?). KISS suggests to disallow it now 
+and see if anyone complains.
+
+(4) I raised this in October, but it ended up at the end of a long thread and 
+it never was discussed:
+
+>Add a new section 6.9, following 6.8 "Expression Functions":
+
+This seems like a curious place to put a new kind of subexpression (being in 
+the subprogram section). About the only relationship this expression has to 
+subprograms is that it can be used in one. :-)
+
+The closest analogs are conditional expressions and declare blocks, so I would 
+have expected it in one of those places. Probably the most sense IMHO would be
+4.5.9 (after quantified expressions, mainly to avoid changing the number on 
+those), as it is just another kind of subexpression. We'd have to move the 
+reduce_expression to 4.5.10 to make room, but since that's new, it doesn't 
+matter. (Anonymous_functions used to be there; *they* would have had a reason 
+to be in chapter 6.)
+
+The alternative of putting it after a declare block (that is, as 5.6.1) 
+doesn't work as well since we already have a new kind of block statement (the 
+parallel block) in that slot.
+
+Another alternative would be to move quantified expressions to 4.5.9 and put 
+declare_expression at 4.5.8. This would have the advantage of putting 
+declare_expression next to the closest relative (conditional_expressions), and 
+also letting quantified_expressions be next to reduction_expressions (as Brad 
+has pointed out several times, a quantified_expression is a special case of a 
+reduction). The problem with that is changing the number of an existing 
+subclause, and the side effects from that (I'd have to rename a bunch of ACATS 
+tests, for instance). So I think this is a bridge too far (just a bit too 
+far).
+
+So I plan to put it at 4.5.9, pending objections.
+
+(5) Another thing I brought up in October: 3.9.2(3) looks like a complete list 
+of possibilities, but it doesn't include conditional_expressions. There is a 
+rule for that in 4.5.7, and it's too tangled to move (it's in multiple 
+sentences and includes a Legality Rule), so I suggested adding a sentence 
+to cross-reference to that to this subclause. That is:
+
+Modify 3.9.2(3):
+
+A name or expression of a tagged type is either statically tagged, dynamically 
+tagged, or tag indeterminate, according to whether, when used as a controlling 
+operand, the tag that controls dispatching is determined statically by the 
+operand's (specific) type, dynamically by its tag at run time, or from context.
+A qualified_expression or parenthesized expression is statically, dynamically, 
+or indeterminately tagged according to its operand. {A declare_expression is 
+statically, dynamically, or indeterminately tagged according to its 
+*body*_expression. A conditional_expression is statically, dynamically, or 
+indeterminately tagged according to rules given in 4.5.7.} For other kinds of 
+names and expressions, this is determined as follows:
+
+I could fix this separately, but that's just more work for me (and more stuff 
+for you guys to read), so I'd rather do it in AI12-0236-1, "while the hood is 
+up", as Steve sometimes has said.
+
+(6) I was asked to come up with an example for the new subclause. I decided 
+to use a Post from the containers as the example. This sort-of violates our 
+usual rules for examples (as it is a forward reference), but I argue that the 
+Ada language-defined packages pre-exists when any reader starts reading the 
+Standard. They don't need any previous declarations to compile the example 
+(just copy some text from the Ada.Containers.Vectors).
+
+Here's the example:
+
+The postcondition for Ada.Containers.Vectors."&" (see A.18.2) could have been 
+written:
+
+   with Post =>
+      (declare
+         Result renames Vectors."&"'Result;
+         Length : constant Count_Type := Left.Length + Right.Length;
+       begin
+         Result.Length = Length and then
+         not Tampering_With_Elements_Prohibited (Result) and then
+         not Tampering_With_Cursors_Prohibited (Result) and then
+         Result.Capacity >= Length)
+
+Note: This is *not* how this is written, as it adds four extra lines to the 
+Post. But the result is a lot easier to read than the original. Note the 
+expanded name for the prefix of Result is required, as an operator symbol
+alone is not a name and thus cannot be a prefix to an attribute. I considered 
+using abbreviations "Res" and "Len" for the object names, but didn't because
+it seemed like lousy Ada practice to worry about saving three characters each.
+
+(7) The example in the !problem is:
+
+   procedure Fgetc (Stream : File_Descr; Result : out Int) with
+     Post =>
+       (if The_File (Cur_Position'Old) = EOF_Ch
+        then Cur_Position = Cur_Position'Old
+          and then Result = EOF
+        elsif The_File (Cur_Position'Old) = ASCII.LF
+        then Cur_Position = Cur_Position'Old
+          and then Result = Character'Pos (ASCII.LF)
+        else
+          Cur_Position = Cur_Position'Old + 1
+          and then Result = Character'Pos (The_File (Cur_Position'Old)));
+
+While I realize that this is not showing all of the declarations, I cannot 
+figure out how a meaningful postcondition would not depend on Stream in some 
+way. I'm guessing the The_File and Cur_Position are components (or functions) 
+of type File_Descr, and the Stream prefix is missing here. Adding that makes 
+this a better example anyway, as it makes it longer still:
+
+   procedure Fgetc (Stream : File_Descr; Result : out Int) with
+     Post =>
+       (if Stream.The_File (Stream.Cur_Position'Old) = EOF_Ch
+        then Stream.Cur_Position = Stream.Cur_Position'Old
+          and then Result = EOF
+        elsif Stream.The_File (Stream.Cur_Position'Old) = ASCII.LF
+        then Stream.Cur_Position = Stream.Cur_Position'Old
+          and then Result = Character'Pos (ASCII.LF)
+        else
+          Stream.Cur_Position = Stream.Cur_Position'Old + 1
+          and then Result = Character'Pos (Stream.The_File (Stream.Cur_Position'Old)));
+
+Then the version using a declare_expression looks like:
+
+   procedure Fgetc (Stream : File_Descr; Result : out Int) with
+     Post =>
+       (declare
+          Old_Pos : constant Position := Stream.Cur_Position'Old;
+          The_Char : constant Character := Stream.The_File (Old_Pos);
+          Pos_Unchg : constant Boolean := Stream.Cur_Position = Old_Pos;
+        begin
+           (if The_Char = EOF_Ch
+              then Pos_Unchg and then Result = EOF
+            elsif The_Char = ASCII.LF
+              then Pos_Unchg and then Result = Character'Pos (ASCII.LF)
+            else
+              Stream.Cur_Position = Old_Pos + 1
+              and then Result = Character'Pos (The_Char)));
+
+which shows the value a bit better.
+
+***************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, January 16, 2019 12:00 AM
+
+Four more: 
+
+(8)
+
+All of the other newish subclauses in 4.5.x have a short introduction. For 
+instance, we have:
+
+Quantified expressions provide a way to write universally and existentially 
+quantified predicates over containers and arrays.
+
+We probably ought to have such a sentence for declare expressions.
+
+    Declare expressions provide a way to include declarations in an 
+    expression, allowing single expressions of incredible complexity.
+
+OK, maybe that's not the best description.
+
+I hoped to steal something from block statements, but their introduction 
+basically repeats the syntax. Ugh.
+
+Stealing the AI summary:
+
+   Declare expressions provide a way to declare local objects and object 
+   renamings in an expression context.
+
+I'll use this until someone has a better idea.
+
+(9)
+
+We have the following Legality Rule:
+
+A declare_item that is an object_declaration shall declare a constant of a 
+nonlimited type.
+
+The reason for this, according to the !discussion:
+
+The restriction to nonlimited types is to avoid implementation difficulties 
+related to build-in-place and task waiting.
+
+But in that case, there needs to be a matching rule for renames, something 
+like:
+
+A declare_item that is an object_renaming_declaration shall rename an object 
+of a nonlimited type.
+
+Since renaming a function is essentially the same as an object declaration. 
+For instance:
+
+     Fooey renames Func_returning_Obj_with_Task_Parts;
+
+The return object has the same lifetime and semantics as a constant object 
+declaration initialized with the same function call.
+
+We could try to allow renaming of existing limited objects only:
+
+   A declare_item that is an object_renaming_declaration shall not rename 
+   an object of a limited type that is a function_call, aggregate, a 
+   parenthesized expression of one of these, a conditional_expression that 
+   has at least one dependent_expression that is one of these, or a 
+   declare_expression whose body_expression is one of these.
+
+Did I forget anything? This isn't particularly pleasant. I'll use the simpler 
+rule pending any discussion.
+
+
+(10) Since we *are* allowing the *body_*expression to be limited (it can only 
+be a build-in-place object in that case), we need an update to 7.5(2.1/5):
+
+In the following contexts, an expression of a limited type is not permitted 
+unless it is an aggregate, a function_call, a raise_expression, a 
+parenthesized expression or qualified_expression whose operand is permitted 
+by this rule, [or] a conditional_expression all of whose dependent_expressions 
+are permitted by this rule{, or a dependent_expression whose body_expression 
+is permitted by this rule}: 
+
+Again, this is consistent with conditional_expressions. (And I've bumped the 
+priority of the ACATS C-Tests for conditional expressions. :-).
+
+
+(11) We should write the syntax on two lines to show the recommended break. 
+We did that for conditional_expression. If a declare expression fits on one 
+line, it probably shouldn't have been used.
+
+Thus:
+
+     declare_expression ::= 
+        declare {declare_item}
+        begin *body_*expression
+
+We could even recommend the best form for longer expressions:
+
+     declare_expression ::= 
+        declare 
+           {declare_item}
+        begin
+           *body_*expression
+
+But that seems like overkill for a default recommendation. (Of course, that's 
+how the example is formatted, it is too large to fit on two lines.)
+
+Whew! Hope that's it.
+
+***************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, January 16, 2019  8:01 AM
+
+I agree with everything you propose except the restriction on renaming 
+functions that return a limited type.  Within an expression you can pass the 
+result of a function that returns a limited object to another function, and 
+in my view, renaming is not harder than parameter passing.  What am I missing?
+It would be nice to have an example to see if there is a real difficulty here.
+
+If there really is a problem, then I would prefer the more complex rule, so 
+you can rename any pre-existing object.
+
+***************************************************************
+
+From: Bob Duff
+Sent: Wednesday, January 16, 2019  11:30 AM
+
+> [Hope the title is clear enough for Bob ;-)]
+
+Crystal.
+
+You got me to read it, anyway.  ;-)
+
+Thanks for finding all these bugs.
+
+I'm OK with your plans, including the later email with "Four more:",
+except:
+
+> (3) ...
+
+I think people will want pragmas.  But as you point out, that could be added 
+later.  So I won't argue the point now.
+
+In fact the "could be added later" argument applies to anything anybody might 
+want to add, like limited stuff. So lets be conservative.
+
+> (8)
+> ...
+>    Declare expressions provide a way to declare local objects and 
+> object renamings in an expression context.
+
+I suggest changing the first "objects" to "constants".
+
+> (10)
+> ...
+> dependent_expressions are permitted by this rule{, or a 
+> dependent_expression whose body_expression is permitted by this rule}:
+
+Is the "dependent_expression" supposed to be "declare_expression"?
+
+***************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, January 16, 2019  12:32 PM
+
+> You got me to read it, anyway.  ;-)
+
+Mission accomplished. :-)
+ 
+> Thanks for finding all these bugs.
+> 
+> I'm OK with your plans, including the later email with "Four more:",
+> except:
+> 
+> > (3) ...
+> 
+> I think people will want pragmas.  But as you point out, that could be 
+> added later.  So I won't argue the point now.
+> 
+> In fact the "could be added later" argument applies to anything 
+> anybody might want to add, like limited stuff.
+> So lets be conservative.
+
+My thought, too. I worry that a lot of pragmas aren't written to make sense 
+in the middle of expressions, and that implementations aren't set up to have
+pragmas in the middle of expressions. Janus/Ada pretty much assumes that the 
+compiler global state (including such things as the suppression state and the
+symboltable) are constant during expression resolution and evaluation.
+Like everything, that could be changed, but doing so would likely be a 
+continual source of bugs.
+ 
+> > (8)
+> > ...
+> >    Declare expressions provide a way to declare local objects and 
+> > object renamings in an expression context.
+> 
+> I suggest changing the first "objects" to "constants".
+
+OK, sounds good to me. I'll change the AI summary, too.
+
+> > (10)
+> > ...
+> > dependent_expressions are permitted by this rule{, or a 
+> > dependent_expression whose body_expression is permitted by
+> this rule}:
+> 
+> Is the "dependent_expression" supposed to be "declare_expression"?
+
+Yup. Getting too late, I guess.
+
+***************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, January 16, 2019  1:05 PM
+
+>> ...
+>> In fact the "could be added later" argument applies to anything 
+>> anybody might want to add, like limited stuff.
+>> So lets be conservative.
+> 
+> My thought, too. ...
+
+I would still like to understand better the restriction against renaming of 
+function calls returning limited types, before agreeing to it.
+...
+
+***************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, January 16, 2019  1:03 PM
+
+> I agree with everything you propose except the restriction on renaming 
+> functions that return a limited type.  Within an expression you can 
+> pass the result of a function that returns a limited object to another 
+> function, and in my view, renaming is not harder than parameter 
+> passing.  What am I missing?  It would be nice to have an example to 
+> see if there is a real difficulty here.
+
+Sigh. You've said this before, Bob and I both have tried to debunk this 
+thought, and it just doesn't seem to stick. I even gave the problematic case
+in my e-mail last night, didn't seem to help.
+
+OK, let's try to motivate this with a long-winded explanation of something 
+that appears obvious.
+
+So, let's assume we have a type that contains one or more tasks.
+
+    type Type_with_Tasks is limited private; 
+
+And we have a function that returns this type:
+
+    function Ugly (A : Integer) return Type_with_Tasks;
+
+This function requires build-in-place, so the implementation is likely to be 
+that a block of memory is passed in, along with a representation of the master 
+to use for the tasks.
+
+We can use this function to declare a constant:
+
+    Fooey : constant Type_with_Tasks := Ugly (12);
+
+The code here will pass into Ugly a block of local memory and the master of 
+this declarative part. We've postulated that this is too messy to allow in the
+declare_expression, so we're disallowing a declaration like this.
+
+Now consider a similar renames:
+
+    Humbug renames Ugly (12);
+
+To create the return object being renames, the code will passing into Ugly a 
+block of local memory and the master of this declarative part. That is,
+*exactly* the same code as the constant. Ergo, if we allow this one, we might 
+as well allow the other as well.
+
+Another way to look at these declarations is to look at the accessibility of 
+the constant (the enclosing entity) and of the renaming (the enclosing 
+entity). Again, these are semantically the same in all visible properties.
+(Indeed, with the new shorter syntax, there is never a reason to write a 
+constant rather than a renaming for a function call.)
+
+There is never really a difference between renaming a function and declaring 
+a similar constant with the function. Even when the type is elementary, the 
+function then returns a value, and in both cases we have to put that value 
+into local memory. There might be a difference for a nonlimited, 
+non-by-reference type in that the constant might make an extra copy, but even 
+then it isn't possible to see that difference other than by inspecting the 
+code.
+
+Now, I can see an argument that the semantics are defined well enough here, 
+so we should allow the renames. But in that case, we should allow the 
+constant, too, since they are semantically identical. There is literally no 
+reason to ban one and allow the other.
+
+However, I think that a large part of the reason for this restriction is that 
+it allowed a number of Bairdian cases where the declared object is part of the
+result of the declare_expression. That is, something like:
+
+    (declare
+        Bah : constant Type_with_Tasks := Ugly (12);
+        Humbug renames Ugly (4);
+     begin
+        (if Tucker > Taft then Bah else Humbug))
+
+Here you might have to build-in-place across multiple levels, and pass the 
+master of the object across multiple levels as well. Sounds like fun. :-)
+ 
+> If there really is a problem, then I would prefer the more complex 
+> rule, so you can rename any pre-existing object.
+
+That's reasonable. In that case, there's no build-in-place nonsense, nor any 
+task waiting issues. You can't declare a constant in that case. And you can't
+use those as a result of a declare_expression (now that I put 
+declare_expression into the 7.5 wording).
+
+***************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, January 16, 2019  2:11 PM
+
+> ...
+> 
+> Now consider a similar renames:
+> 
+>    Humbug renames Ugly (12);
+> 
+> To create the return object being renames, the code will passing into 
+> Ugly a block of local memory and the master of this declarative part. 
+> That is,
+> *exactly* the same code as the constant. Ergo, if we allow this one, 
+> we might as well allow the other as well.
+
+I agree to stop beating this dead horse, but I would still like to understand 
+how things are different if we pass the return value as a parameter to 
+another function call.  In that case, what is the master of the task, 
+presuming there is one?
+
+I'll try to answer my own question...
+
+The Heart-of-darkness RM 3.10.2(8) says:
+
+  "The accessibility level of a view of an object or subprogram defined by a 
+  renaming_declaration is the same as that of the renamed view."
+
+Then 3.10.2(10.1/3,10.6/3) say:
+
+  "The accessibility level of the result of a function call is that of the 
+  master of the function call, which is determined by the point of call as follows:
+...
+  * In other cases, the master of the call is that of the innermost master 
+    that evaluates the function call."
+
+OK, so according to 7.6.1(3/2), whether we pass the result as a parameter to 
+another call, or we rename the result in a declare_expression, the master is 
+an enclosing expression (or the declare_expression itself), function_call, or
+range, that is not itself within an expression, function_call, or range.
+
+An object_renaming is not considered an object_declaration (by syntax), and 
+according to 9.2(2/2), it is the tasks created by the elaboration of an 
+object_declaration or generic associations of mode IN that are all activated 
+together at the "begin" of the declarative part.  The tasks associated with a
+renamed function call are therefore treated like objects that are *not* 
+created by object_declarations, and according to 9.2(4/2), that means they 
+are activated immediately after completing their initializations, or if 
+being returned by a function, after having been returned from the function.
+So this implies that the tasks, if any, are activated immediately upon return
+of the function, whether we rename the result or pass it as a parameter to 
+another subprogram.
+
+All in all I don't see much of a difference.  Be that as it may, I can accept 
+(grudgingly ;-) that for some implementations, renaming such a function call 
+is somehow more complicated than just passing the result on to another 
+subprogram call, so it is worth disallowing the renaming of such functions in 
+a declare_expression.  So long as we are allowed to rename pre-existing 
+limited objects, I don't think we are losing any significant functionality.
+
+> Another way to look at these declarations is to look at the 
+> accessibility of the constant (the enclosing entity) and of the 
+> renaming (the enclosing entity). Again, these are semantically the same in 
+> all visible properties. (Indeed, with the new shorter syntax, there is never 
+> a reason to write a constant rather than a renaming for a function call.)
+
+I believe the time when task activation occurs is different between these two.
+You need to put the tasks that are part of a local stand-alone object onto a 
+list for activation at the point of the "begin," whereas with renaming, you 
+can activate immediately,
+> 
+> There is never really a difference between renaming a function and 
+> declaring a similar constant with the function.
+
+I believe there can be a significant performance difference when renaming vs. 
+copying results of an unknown size in some implementations.
+
+> ...
+> Now, I can see an argument that the semantics are defined well enough 
+> here, so we should allow the renames. But in that case, we should 
+> allow the constant, too, since they are semantically identical. There 
+> is literally no reason to ban one and allow the other.
+
+I don't agree, because if we allow a stand-alone object with task parts, we 
+would probably need to establish an activation list and do something 
+appropriate at the "begin," as well as probably adjust the wording in 9.2 
+somewhat since it presumes that a "begin" is followed by a sequence of 
+statements.  So I am definitely *not* asking for non-limited constants.
+ 
+> However, I think that a large part of the reason for this restriction 
+> is that it allowed a number of Bairdian cases where the declared 
+> object is part of the result of the declare_expression. That is, something like:
+> 
+>    (declare
+>        Bah : constant Type_with_Tasks := Ugly (12);
+>        Humbug renames Ugly (4);
+>     begin
+>        (if Tucker > Taft then Bah else Humbug))
+
+I don't see how we are avoiding this, since presumably I can write:
+
+    (if Tucker > Taft then Ugly(12) else Ugly(4));
+ 
+***************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, January 16, 2019  3:11 PM
+
+...
+> An object_renaming is not considered an object_declaration (by 
+> syntax), and according to 9.2(2/2), it is the tasks created by the 
+> elaboration of an object_declaration or generic associations of mode 
+> IN that are all activated together at the "begin" of the declarative 
+> part.  The tasks associated with a renamed function call are therefore 
+> treated like objects that are *not* created by object_declarations, 
+> and according to 9.2(4/2), that means they are activated immediately 
+> after completing their initializations, or if being returned by a 
+> function, after having been returned from the function.  So this 
+> implies that the tasks, if any, are activated immediately upon return 
+> of the function, whether we rename the result or pass it as a 
+> parameter to another subprogram.
+
+Interesting. I wonder if we do that right? This is the first I've heard of 
+this difference (at least in a long time, perhaps I've forgotten that it 
+exists).
+
+> All in all I don't see much of a difference.  Be that as it may, I can 
+> accept (grudgingly ;-) that for some implementations, renaming such a 
+> function call is somehow more complicated than just passing the result 
+> on to another subprogram call, so it is worth disallowing the renaming 
+> of such functions in a declare_expression.  So long as we are allowed 
+> to rename pre-existing limited objects, I don't think we are losing 
+> any significant functionality.
+
+I agree that there isn't much difference, but I claim (still) that there is 
+not much difference with an object_declaration, either. And I'm postulating 
+that that is not work that we want to do. If so, we can't want to do similar 
+work, either.
+
+> > Another way to look at these declarations is to look at the 
+> > accessibility of the constant (the enclosing entity) and of the 
+> > renaming (the enclosing entity). Again, these are semantically the 
+> > same in all visible properties.
+> > (Indeed, with the new shorter syntax, there is never a reason to 
+> > write a constant rather than a renaming for a function call.)
+> 
+> I believe the time when task activation occurs is different between 
+> these two.  You need to put the tasks that are part of a local 
+> stand-alone object onto a list for activation at the point of the 
+> "begin," whereas with renaming, you can activate immediately,
+
+Creating that list happens inside the function when the return object is 
+created, so there is going to be a list either way. Precisely where one calls 
+TKActivate is hardly a big deal!
+
+> > There is never really a difference between renaming a function and 
+> > declaring a similar constant with the function.
+> 
+> I believe there can be a significant performance difference when 
+> renaming vs. copying results of an unknown size in some 
+> implementations.
+ 
+But we're talking about functions of a type which requires build-in-place.
+There's never any copying there.
+
+And even for other types, an implementation that is building a separate 
+temporary object is working harder than necessary (there never is a need to
+have a such an object as there is with :=). In any case, an implementation is
+allowed to remove such a copy, so there need be no difference. I don't think 
+we should compare the easiest possible implementation here (or anywhere); it 
+matters much more that the semantics are essentially identical. 
+
+> > ...
+> > Now, I can see an argument that the semantics are defined well 
+> > enough here, so we should allow the renames. But in that case, we 
+> > should allow the constant, too, since they are semantically 
+> > identical. There is literally no reason to ban one and allow the other.
+> 
+> I don't agree, because if we allow a stand-alone object with task 
+> parts, we would probably need to establish an activation list and do 
+> something appropriate at the "begin," as well as probably adjust the 
+> wording in 9.2 somewhat since it presumes that a "begin" is followed 
+> by a sequence of statements.  So I am definitely *not* asking for 
+> non-limited constants.
+
+You always have an activation list, because the tasks are created inside the 
+function and activated outside in every case, and how else are you going to 
+communicate that? As I said before, precisely the location that the list is 
+activated is pretty much a trivial difference.
+
+Indeed, Janus/Ada doesn't have any mechanism other than an activation list for 
+tasks. I wasn't aware of any case in Ada where tasks are activated immediately 
+upon creation; there's always a short delay to at least the end of the 
+construct. And, since in almost all such cases (like aggregates and
+functions) the code is shared with cases that activate much later, it doesn't 
+even make sense to bother with other models (why be more complex than needed? 
+Task activation isn't on the critical performance path for any program). I 
+doubt that most Ada runtimes support anything other than list activation (it
+has to be part of the runtime, since all of the tasks have to become ready at
+the same instant - you can't do that with an explicit list walk that activates
+each task in turn).
+
+So, as previously noted, I see virtually no difference here, at least for 
+implementation purposes. The only difference is where the list is activated,
+which is trivial. (Indeed, based on the semantics above, the renames is 
+marginally more expensive, since we have to create an empty list specifically 
+for each renames; there's only one for all objects.)
+
+> > However, I think that a large part of the reason for this 
+> > restriction is that it allowed a number of Bairdian cases where the 
+> > declared object is part of the result of the declare_expression.
+> > That is, something like:
+> > 
+> >    (declare
+> >        Bah : constant Type_with_Tasks := Ugly (12);
+> >        Humbug renames Ugly (4);
+> >     begin
+> >        (if Tucker > Taft then Bah else Humbug))
+> 
+> I don't see how we are avoiding this, since presumably I can write:
+> 
+>     (if Tucker > Taft then Ugly(12) else Ugly(4));
+
+This is a direct build-in-place, which already has to work. It's bringing 
+temporary objects into the picture that causes trouble. The good news is the 
+example I wrote is clearly illegal, as it violates 7.5(2.1). So I don't 
+remember the exact example (or if it was actually legal, or whether it was 
+already plugged).
+
+***************************************************************
+
+From: Bob Duff
+Sent: Wednesday, January 16, 2019  3:40 PM
+
+I'm somewhat confused by this thread.
+
+Is a declare_expression a master?  Does it await termination of nested tasks
+and/or finalize nested objects?
+
+...
+> ...all of the tasks have to
+> become ready at the same instant - you can't do that with an explicit 
+> list walk that activates each task in turn).
+
+You can.  First sort the list in decreasing order by priority, and raise one's 
+own priority to the max of the activatees.
+
+> > >    (declare
+> > >        Bah : constant Type_with_Tasks := Ugly (12);
+> > >        Humbug renames Ugly (4);
+> > >     begin
+> > >        (if Tucker > Taft then Bah else Humbug))
+
+> ...The good news is the
+> example I wrote is clearly illegal, ...
+
+OK, good.  I was about to ask "Isn't that illegal?!".
+
+***************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, January 16, 2019  3:42 PM
+
+>> ...
+> 
+> This is a direct build-in-place, which already has to work. It's 
+> bringing temporary objects into the picture that causes trouble.
+
+This is where I always get confused.  You need some sort of temporary object 
+when you call a function, whether you rename its result or pass it along to 
+another subprogram call.  We aren't disallowing calling functions that return
+tasks inside a declare_expression somewhere, we are merely disallowing 
+renaming the result so you can use it multiple times.  The object doesn't go
+away until the whole declare_expression goes away in any case, so the 
+lifetime isn't being expanded.
+
+In any case, "uncle." ;-)
+
+***************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, January 16, 2019  3:45 PM
+
+> I'm somewhat confused by this thread.
+> 
+> Is a declare_expression a master?  Does it await termination of nested 
+> tasks and/or finalize nested objects? ...
+
+I am presuming a declare_expression is not a master unless it is used in a 
+context where any sort of expression would be a master, namely, it is used in
+a context that is not enclosed by another expression, function_call, range, or
+simple_statement.
+
+***************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, January 16, 2019  4:17 PM
+
+> I am presuming a declare_expression is not a master unless it is used 
+> in a context where any sort of expression would be a master, namely, 
+> it is used in a context that is not enclosed by another expression, 
+> function_call, range, or simple_statement.
+
+That's my understanding of the rules as well. Part of the reason that we 
+wanted to avoid task waiting and the like is that it doesn't make a lot of 
+sense in the declare_expression is not a master scenario.
+
+I admit that I didn't realize that task activation is different for renaming 
+of a function result. [This seems like a bug to me, since it is the only 
+semantic difference from the similar object declaration (finalization and task 
+waiting happening at the same point for both cases), and I'd hate to see people
+renaming function results specifically to get this behavior -- that seems 
+incredibly confusing. I think it's much more likely to be a surprise that the 
+tasks activate early. But way too late to change anything here, since this is 
+an Ada 95 feature reimagined by Ada 2005.] So for the single case of task 
+waiting, there is some reason to treat renames and constants differently. (Not 
+so much for build-in-place, but no one seems to remember the issue for that, so
+it's hard to discuss!)
+
+In any case, I think we all agree that there is no issues with renaming of 
+existing objects (and you can't declare a constant of those anyway), so it 
+probably makes sense to allow that. Otherwise, we'll start out conservative
+and see how much complaining there is.
+
+Bob wrote:
+
+>> ...all of the tasks have to
+>> become ready at the same instant - you can't do that with an explicit 
+>> list walk that activates each task in turn).
+>
+>You can.  First sort the list in decreasing order by priority, and 
+>raise one's own priority to the max of the activatees.
+
+I suppose, but that's complex enough that you're not going to do it in-line.
+(A list sort of a list of unknown length in-line? Followed by a priority 
+change, a list walk, and another priority change? Nope.) So the general case 
+is going to be in a library subprogram, and what you do inside of that 
+(something like the above would be necessary for a threaded implementation, I 
+presume) isn't very interesting.
+
+You could of course optimize it if you somehow know how many tasks are on the 
+list (as in the directly declared case), especially if there is only one task 
+to activate. But it doesn't seem critical enough to spend time/space on, it's 
+hard to imagine a case where the cost to activate a task is on the critical 
+performance path. Seems like there are zillions of more likely things to 
+optimize.
+
+***************************************************************
+
+From: Bob Duff
+Sent: Wednesday, January 16, 2019  4:36 PM
+
+> I suppose, but that's complex enough that you're not going to do it in-line.
+
+Right.  I didn't mean to imply that it should be done inline.
+Just that you don't need an atomic "make many tasks ready"
+operation.  (Actually, I think I was wrong to say "raise one's own priority 
+to the max of the activatees".  I don't think that's necessary.)
+
+But anyway, never mind all that, this is of course a side issue.
+
+***************************************************************
+
+From: Bob Duff
+Sent: Wednesday, January 16, 2019  4:19 PM
+
+> I am presuming a declare_expression is not a master unless it is used 
+> in a context where any sort of expression would be a master, namely, 
+> it is used in a context that is not enclosed by another expression, 
+> function_call, range, or simple_statement.
+
+OK, so:
+
+    declare
+        X: Integer := (declare Y: T; begin 123);
+    begin
+        ...
+    end;
+
+If T has finalization and tasks, when does Y get finalized, and when are the 
+tasks in Y activated and when do we await their termination?
+
+Now change it to:
+
+    declare
+        X: Integer;
+    begin
+        X := (declare Y: T; begin 123);
+        ...
+    end;
+
+Does that change things?  (Now the decl_expr is enclosed by a simple
+statement.)
+
+***************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, January 16, 2019  4:38 PM
+
+> OK, so:
+> 
+>     declare
+>         X: Integer := (declare Y: T; begin 123);
+
+This is illegal, because of (A) missing "constant" and (B) limited objects 
+aren't allowed. We were only discussing the renames of a function case.
+
+>     begin
+>         ...
+>     end;
+> 
+> If T has finalization and tasks, when does Y get finalized, and when 
+> are the tasks in Y activated and when do we await their termination?
+
+So let's write an example of interest:
+
+    function Fun return T;
+
+     declare
+         X : Integer := (declare Y renames Fun; begin 123);
+     begin
+         ...
+     end;
+
+Here Y's tasks are activated as soon as the function returns (according to 
+Tucker's reading of the rules that surprised me), Y gets finalized and task
+awaited after the completion of the declaration of X.
+
+> Now change it to:
+> 
+>     declare
+>         X: Integer;
+>     begin
+>         X := (declare Y: T; begin 123);
+          X := (declare Y renames Fun; begin 123);
+>         ...
+>     end;
+> 
+> Does that change things?  (Now the decl_expr is enclosed by a simple
+> statement.)
+
+Only at the end of the assignment statement.
+
+Note that Tucker compare this to the case of parameter passing. An example of 
+what he's talking about:
+
+     function Real_Fun (X : in T; N : in Natural) return Integer;
+
+     declare
+         X : Integer := (declare C : constant Natural := 12; begin Real_Fun(Fun, C));
+     begin
+         ...
+     end;
+
+Here, the result of Fun is activated after Fun returns and before Real_Fun is 
+called. The return object is finalized and its tasks awaited when the entire 
+object_declaration for X is finished.
+
+For obvious reasons, we can't disallow this sort of thing in a 
+declare_expression, especially as it is allowed in any existing expression.
+
+-----
+
+In any case, we've agreed (because I've worn out Tucker :-) to only allow 
+limited renames in the case of existing objects (not function calls). So both 
+of these examples are illegal in the rules as written. That is the 
+conservative choice, and it is hard to imagine that rule causing any new 
+hardships (there are plenty of *old* hardships - like the parameter passing 
+case above, but we're stuck with those). Such a rule would allow everything 
+that seems likely.
+
+I think that if people start bumping into this and complaining, we can change 
+that in Corrigendum 1 for Ada 2020. If we allow it and there are 
+implementation issues, we're stuck.
+
+***************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, January 16, 2019  4:53 PM
+
+> OK, so:
+> 
+>    declare
+>        X: Integer := (declare Y: T; begin 123);
+>    begin
+>        ...
+>    end;
+> 
+> If T has finalization and tasks, when does Y get finalized, and when 
+> are the tasks in Y activated and when do we await their termination?
+
+We aren't allowing limited types nor variables.  But I'll try to answer your 
+question presuming this is legal.  I guess the finalization part is allowed, 
+so that is still a relevant question.
+
+In any case, the tasks would be activated, probably at the begin if we allowed
+this.  If it were a renaming of a function_call, the tasks would presumably be
+activated immediately upon return from the function call being renamed.
+
+Finalization will happen when we complete the evaluation of the 
+declare_expression, because it is itself a master in this context.  If we 
+allowed tasks, they would be awaited then as well.
+
+I believe this general timing would apply very similarly for an "if" 
+expression that called a function that returned a task and then passed it to 
+another function.
+
+If the declare_expression (or "if" expression) were to return a task itself, 
+then RM 3.10.2(16.1/3) will presumably apply, and the master of that returned 
+object would *not* be the declare_expression, but rather be the same as X.
+
+> Now change it to:
+> 
+>    declare
+>        X: Integer;
+>    begin
+>        X := (declare Y: T; begin 123);
+>        ...
+>    end;
+> 
+> Does that change things?  (Now the decl_expr is enclosed by a simple
+> statement.)
+
+The finalization won't happen until the assignment is complete.  If we allowed 
+tasks, they would be activated presumably at the same time as in the earlier 
+case, and then awaited when finalization occurs, which is at the end of the 
+statement.
+
+This would clearly not be legal if the declare_expression were itself yielding 
+a task object, so we don't need to answer that one.
+
+3.10.2(16.1/3) is pretty critical as far as determining the rules for the 
+"body_expression".  But for other stuff happening inside the 
+declare_expression, it all gets finalized pretty quickly.
+
+***************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, January 16, 2019  4:56 PM
+
+> So let's write an example of interest:
+> 
+>    function Fun return T;
+> 
+>     declare
+>         X : Integer := (declare Y renames Fun; begin 123);
+>     begin
+>         ...
+>     end;
+> 
+> Here Y's tasks are activated as soon as the function returns 
+> (according to Tucker's reading of the rules that surprised me), Y gets 
+> finalized and task awaited after the completion of the declaration of X.
+
+Actually, I believe it gets finalized before that, just like an "if" 
+expression.  It would get finalized when the declare_expression is done, 
+since the declare_expression is the 
+outermost expression/function-call/range/simple-statement.
+
+Individual declarations are not masters generally, unlike simple statements.
+
+***************************************************************
+
+From: Bob Duff
+Sent: Wednesday, January 16, 2019  5:01 PM
+
+> I think that if people start bumping into this and complaining,...
+
+If customers complain to AdaCore, then I can implement it.
+Don't need permission from ARG.  Or if I run out of more important things to 
+do, I'll implement it.
+
+Then we can ask ARG to standardize, wait for it, ...
+"existing practice".  ;-)
+
+So Tuck should push me to implement it next year, rather than pushing ARG 
+this year.
+
+>... If we allow it and there are
+> implementation issues, we're stuck.
+
+Right.
+
+***************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, January 16, 2019  5:36 PM
+
+> > Here Y's tasks are activated as soon as the function returns 
+> > (according to Tucker's reading of the rules that surprised me), Y 
+> > gets finalized and task awaited after the completion of the 
+> > declaration of X.
+> 
+> Actually, I believe it gets finalized before that, just like an "if" 
+> expression.  It would get finalized when the declare_expression is 
+> done, since the declare_expression is the outermost 
+> expression/function-call/range/simple-statement.
+> 
+> Individual declarations are not masters generally, unlike simple 
+> statements.
+
+You're right that I need to reread the rules before answering questions like 
+this. There are cases where you'd be wrong, but this isn't one of them.
+There definitely are cases where parts of expressions (parameters) essentially 
+get their master an extra level out, and those were the sorts of cases I was 
+thinking about here.
+
+Assuming we have the accessibility rules correct, then there are interesting 
+cases.
+
+    type T2 is tagged ... -- Assume controlled part(s).
+
+    type T3 is private; -- A composite type.
+
+    function Fun2(I : in Integer) return T2;
+    function Fun3(X : in out aliased T2) return T3;
+
+    declare
+       X : T3 := (declare Y renames Fun2 (12);
+                  begin Fun3 (Y));
+       Z : T3 := (declare
+                  begin Fun3 (Fun2 (12));
+    begin
+       ...
+    end;
+
+X is illegal, I think, because Y has the accessibility of the expression, 
+while the parameter to Fun3 has to have the accessibility of the "master of 
+the call", which is the master of X. (See 6.4.1.) OTOH Z is legal, I think, 
+because the master of the call of Fun2 is that of Fun3 (we don't define these 
+things in such a way to ensure that they would always fail an accessibility 
+check), so the results of both of these functions get finalized with X. That 
+might be rather late, but at least it isn't wrong. (This is the infamous 
+3.10.2(10.2/3) and 3.10.2(10.5/3).)
+
+Just think, the introduction of declare_expressions will give us many new ways 
+to fail accessibility checks. The ACATS tester in me can't wait. ;-)
 
 ***************************************************************
 

Questions? Ask the ACAA Technical Agent