Version 1.3 of ai12s/ai12-0402-1.txt

Unformatted version of ai12s/ai12-0402-1.txt version 1.3
Other versions for file ai12s/ai12-0402-1.txt

!standard 3.10.2(10.2/3)          20-12-11 AI12-0402-1/03
!class Amendment 20-10-15
!status Amendment 1-2012 20-12-11
!status ARG Approved 13-0-1 20-12-09
!status work item 20-10-15
!status received 20-10-15
!priority Low
!difficulty Medium
!subject Master of a function call with elementary result type
!summary
The master of the function call for a function whose result type is a scalar or named access type is always the innermost master invoking the function.
!problem
When passing an actual object to an aliased formal, if the subprogram called is a function, we require that the actual not be statically deeper than the master of the function call. On the other hand, if it is a procedure, there is no accessibility requirement for the actual. The question is what happens when the function returns something like a simple scalar value.
Here is an example of this case:
function F1 (X : aliased T1) return T2;
function F2 return T2 is Local : aliased T1 := ...; begin return F1 (Local); -- Should be allowed if T2 is of an elementary type. end;
Similarly, if the function call is used to define a component of an object created by an allocator, such as:
Local : aliased T1 := ... X : Lib_Level_Access := new Lib_Level'(A => F1 (Local)); -- Should be legal if T2 is of an elementary type.
!proposal
We propose to change the rules for determining the master of the function call, by recognizing the case where the result is of an elementary type. The default rule makes the master of the function call be the innermost master invoking the function, and that is the fallback we want.
Note that master of the function call is a dynamic semantics notion, though there is a statically-deeper check between the accessibility level of the master and the actual object passed to an aliased formal (6.4.1(6.4/3)), so we need to keep those static checks in mind.
!wording
Modify 3.10.2(10.2/3):
* If {the result type at the point of the function (or access-to-function type) declaration is a composite type, and} the result is used (in its entirety) to directly initialize part of an object, the master is that of the object being initialized. In the case where the initialized object is a coextension (see below) that becomes a coextension of another object, the master is that of the eventual object to which the coextension will be transferred.
!discussion
We restrict bullet 3.10.2(10.2/3) to apply only if the function result is declared to be of a composite type. This makes sense since only results of a composite type (or of an anonymous access type, which are handled separately already) are potentially affected by the master of the function call. Note that a private type is considered composite, so this result presumes the worst for a function returning a private type. We could have made the rule more complex, depending on whether the result might be built in place, or might have an access discriminant, but we chose to make the minimal change.
The wording says "the result type at the point of function declaration is a composite type," to make it clear that this depends on the properties at the point of the declaration of the function, rather than properties that might be known at the point of call or inside the function body. In particular, a type that is untagged private at the declaration of the function might be known to be elementary at the point of call or inside the body of the function, but we still treat such a case as "composite" to avoid breaking privacy, and to have a consistent rule for all callers of the function.
!examples
Looking at our two examples:
function F1 (X : aliased T1) return T2;
function F2 return T2 is Local : aliased T1 := ...; begin return F1 (Local); -- Is legal so long as T2 is an elementary type at the point -- of the declaration of F1. end;
In the case where the result is used to initialize a component of an allocated object:
Local : aliased T1 := ... X : Lib_Level_Access := new Lib_Level'(A => F1 (Local)); -- Is legal so long as T2 is an elementary type at the point -- of the declaration of F1.
!ASIS
No changes needed.
!ACATS test
ACATS B- and C-Tests are needed to check that the checks and master apply only in the appropriate cases.
!appendix

Editor's Note, Oct 15, 2020: I'm concerned that this change (as described in
version /01) causes issues with build-in-place, adds a maintenance hazard, and 
adds a runtime incompatibility for potentially any function result with a part
of an access type. Moreover, the exact proposal breaks privacy for a Legality 
Rule, something we never do outside of representation aspects.

Discussions are ongoing, but I certainly do not believe this AI is ready for
prime time.

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

From: Tucker Taft
Sent: Wednesday, October 21, 2020  8:00 AM

> Following is the Final Agenda for ARG electronic meeting #62G, October 
> 21, 2020, 10:30 AM EDT (-4 UTC) ...
> 
> Other new, minor Amendment [personally, I don't think this one is 
> ready for review/approval. Perhaps a newer version will be by the time 
> of the
> meeting]:
> 
> AI12-0402-1/01   2020-10-15 --  Master of a function call with no special
> result type
> ...

The goal of this AI was to reduce the number of cases where we checked the 
accessibility level of the aliased actual passed to an aliased formal.  This
arose from an AdaCore customer question, where they wanted to use the aliased
formal to allow the use of 'Access inside, but were surprised this didn't work
if the aliased actual was a local variable of the caller, and the function call
was returned as a result of the enclosing function.

I believe Randy's main concern is with this paragraph:

Modify 3.10.2(10.2/3):

  {If the result is of a class-wide type, or the (specific) result
  subtype has an unconstrained access discriminant, or has a part that
  is of an immutably limited or limited private type, then:

---

His concern is that by limiting to only the specified sort of result types, 
there might be existing Ada 2012 programs that presume the accessibility check
has been made against the aliased actual which would no longer work because the
result type doesn't fall within the new limited set.

So here is an alternative, which includes essentially any type that might 
contain an access value buried within it:

Modify 3.10.2(10.2/3):

  {If the result is of a class-wide or limited type, or the
  result type has any (visible) subcomponents that are of an access
  type or visible parts that are of a type that is private or a private
  extension:

  ... [as in the AI]

If we end up discussing this today in the ARG meeting, I would suggest we 
start from this new version of the introductory paragraph.

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

From: Tucker Taft
Sent: Wednesday, October 21, 2020  1:33 PM

Here is the simpler wording I came up with for the introductory paragraph:

Modify 3.10.2(10.2/3):

  {In the case where the result is of a composite type, but is not of a
  specific composite type all of whose elementary subcomponents are
  visible and scalar:

  ... [rest as in the AI]

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

From: Tucker Taft
Sent: Saturday, October 24, 2020  6:39 AM

I realized that we could accomplish much of what we wanted with something even 
simpler:

Modify 3.10.2(10.2/3):

   {In the case where the result is of a composite type:

   ... [rest as in the AI]

---

In other words, only if you return a composite type do these rules apply.  I 
think that makes more sense in general, and would help to clarify rather than 
add complexity, since at least one of the rules talks about using the result 
in its "entirety" which is of course redundant for an elementary type.

On the other hand, suppressing the rules for some special composite types is 
probably not worth it, because as Arnaud points out, we would prefer to 
simplify, not add complexity, to 3.10.2 these days.

With the above, a simple function that returns a scalar or named access type 
would be treated effectively like a procedure.  Anything more complex than 
that would do the accessibility checks on aliased actuals. 

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

Questions? Ask the ACAA Technical Agent