!standard 3.10.2(13.4/4) 19-09-30 AI12-0345-1/01 !standard 13.11.4(21/3) !standard 13.11.4(31/3) !class binding interpretation 19-09-30 !status work item 19-09-30 !status received 19-09-17 !priority Low !difficulty Easy !qualifier Omission !subject Dynamic accessibility of explicitly aliased parameters !summary An explicitly aliased parameter has the accessibility of a normal parameter in all cases except when compared to the master of the call (which is defined to pass). !question 3.10.2(13.4/4) says: The accessibility level of an explicitly aliased (see 6.1) formal parameter in a function body is determined by the point of call; it is the same level that the return object ultimately will have. This implies that the dynamic level has to be passed in for all such functions, in case the parameter is used in a context that requires a dynamic level (for instance, as an access parameter). Is this intended? (No.) !recommendation (See Summary.) !wording Replace 3.10.2(13.4/4) with: The accessibility level of an explicitly aliased (see 6.1) formal parameter in a function body the same as any other formal parameter, except that it is defined to match the level of the master of the call when compared to the level of the return object of the function. AARM Reason: We make checks on the actual object for an explicitly aliased parameter of a function to ensure that it can be returned, so we define that no checks are ever needed in that case. For all other uses, it acts the same as any other parameter (that is, it is treated as local to the function). AARM Implementation Note: If the dynamic level of an explicitly aliased parameter is needed for some purpose, it is local to the function -- it is never necessary to pass in the actual level of the call for explicitly aliased parameters. Note that the matching defined here can be implemented by simply omitting any check in the case where one is matching an explicitly aliased parameter to the master of the call. !discussion The intent of the primary designer of explicitly aliased parameters (that would be the author of this AI) was that explicitly aliased parameters act the same as any other parameter vis-a-vis accessibility except when comparing against the "master of the call" (that is, the accessibility of the return object). In that case, we do accessibility checks on the actual to ensure that it is safe to return, so no checks are ever needed in the return. This model ensures that no dynamic accessibility information is ever needed for an explicitly aliased parameter, even when the function result needs such information. The wording attempted to accomplish this model with a paired static and dynamic model, assuming/requiring that any cases that would be problematic would be illegal statically. However, it is clear that both stand-alone objects of an anonymous access type, and calls using access parameters can store the dynamic accessibility of an explicitly aliased parameter, and thus it would need to be passed. Therefore, we reword the dynamic accessibility of explicitly aliased parameters to match the intended model exactly. --- An alternative model was proposed where the dynamic accessibility of an explicitly aliased parameter would be that of the return object, if the implementation would have to pass the level along with a call. This model would also have no additional cost, but it would have a maintenance hazard, as the accessibility of the parameter could change if the return type is changed (possibly even if only the private components of some hidden part of the return type is changed). This could cause working code to suddenly start raising Program_Error rather mysteriously. [Author's note: Steve's proposal makes large changes to the accessibility model for explicitly aliased parameters. That seems dangerous, accessibility is confusing enough without changing wording that we have some (small? :-) level of confidence in. I'd prefer to change as little as possible, especially as the intent was that no one could ever see the (real) dynamic accessibility level of an explicitly aliased parameter. Steve didn't provide any of the examples that caused this discussion (I have to assume there were some, so it's impossible to tell if the "easy"] !ASIS No ASIS effect. !ACATS test !appendix From: Steve Baird Sent: Tuesday, September 17, 2019 6:32 PM There was some internal discussion within AdaCore a while back about some possible minor changes to the accessibility rules for explicitly aliased parameters. This is a description of those changes and their motivation. No specific wording is proposed; at this point the goal is only to determine whether it makes sense to produce wording for a more specific proposal. Tuck believes that this proposal reflects the original intent of the language designers back when explicitly aliased parameters were added to the language and so this is just a matter of correcting the RM to reflect that original intent. In any case, it seems that it would simplify implementations without costing users any useful functionality. Dynamic semantics: The current RM wording distinguishes between a function and other callable entities (e.g., procedures, entries) in defining the accessibility level of an explicitly aliased parameter. Instead, we want to distinguish a function whose result type requires (at runtime) passing in an accessibility level parameter from other callable entities. Note that the details of the rules to capture this distinction, whatever those details are, have nothing to do with explicitly aliased parameters. The idea is that if we are already passing in (at the implementation level) an accessibility level parameter to indicate the level of the master of the call, then that parameter also defines the accessibility level of any explicitly aliased parameters. If we are not already passing in such a parameter, then the accessibility level of any explicitly aliased parameters is the same as that of any other parameters (or, for that matter, of any local variables declared immediately within the callable entity). Either way, we never have to introduce a new implicit parameter just for an explicitly aliased parameter - we either reuse a parameter that was already being passed in for another reason or we don't need an implicit parameter at all. This simplifies the implementation. This relies on the fact (we hope and believe it is a fact) that if no function-result-accessibility-level implicit parameter is passed in, then there will be no dynamic accessibility checks comparing the level of an explicitly aliased parameter with the level of the function result object. If such a check were ever performed then it would fail (because in that case the accessibility level of the explicitly aliased parameter is the same as that of a local variable) and that would be bad. We believe this is not a problem because no such check will be performed. Some additional details we didn't really discuss, but which seem worth noting: There will be some RM wording work in precisely defining the predicate that determines which category a function falls into. If the result type is class-wide, or has at least one access discriminant, or has a subcomponent subtype which is unconstrained and has at least one access discriminant (yes, this is possible), then an accessibility level parameter is needed. Probably also for the case where the result type is an anonymous access type. It is proposed that the type of an explicitly aliased parameter plays no role in determining its accessibility level. Given a function result type like type Result_Type (X : access Integer) is null record; and an explicitly aliased parameter like Str : aliased String; one could imagine noticing that the function result couldn't possibly contain a reference to any part of the parameter and therefore the accessibility level of the parameter could be defined as for a parameter of a procedure. That is not what is being proposed here. Static semantics: Scrap the distinction of being in a return statement/expression vs. not. Keep, at least in effect, the existing rule when determining whether the accessibility level of an explicitly aliased parameter of F is statically deeper than the level of the return object of F, the level of the return object is considered to be the same as that of the level of the explicitly aliased parameter Note that making this rule apply throughout the entire function body instead of only within a return statement/expression should have no effect because no comparisons where the rule makes a difference are possible outside of a return statement/expression. Thus, eliminating the distinction is non-essential semantics-preserving cleanup. Opinions? **************************************************************** From: Jeff Cousins Sent: Thursday, September 19, 2019 7:11 AM The motivation seems good, and the proposal seems reasonable as far as I can tell, but it would be a brave man who made any definitive statements on dynamic accessibility checking. **************************************************************** From: Richard Wai Sent: Saturday, September 21, 2019 12:51 PM > The idea is that if we are already passing in (at the > implementation level) an accessibility level parameter to indicate > the level of the master of the call, then that parameter also > defines the accessibility level of any explicitly aliased > parameters. This seems to mean that, for example, procedures with explicitly aliased parameters would have an accessibility level potentially above the local level. So for example, this would be legal (currently not): declare type Element is ...; type Element_Access is access all Element; type pointer is Record Ref: Element_Access; End record; procedure Relink (Ptr: in out Pointer; E: aliased in out Element) is begin Ptr.Ref := E'Access; end Relink; A,B: aliased Element; Ptr_A, Ptr_B: Pointer; begin Ptr_A.Ref := A'Access; Ptr_B.Ref := B'Access; Relink (Ptr_B, A); End; Am I misunderstanding this? I get the feeling that this is specifically intended for function and their return objects specifically (kind of as it was before), but this isn't very clear from what I read.. **************************************************************** From: Gary Dismukes Sent: Monday, September 23, 2019 11:55 AM > > The idea is that if we are already passing in (at the > > implementation level) an accessibility level parameter to indicate > > the level of the master of the call, then that parameter also > > defines the accessibility level of any explicitly aliased > > parameters. > > This seems to mean that, for example, procedures with explicitly aliased > parameters would have an accessibility level potentially above the local > level. My understanding is that this would only affect functions whose return type requires passing in a run-time accessibility level, so doesn't affect procedures at all. > So for example, this would be legal (currently not): No, the legality of your example would not be affected by this rule change/clarification, AFAIK. > declare > type Element is ...; > type Element_Access is access all Element; > > type pointer is > Record > Ref: Element_Access; > End record; > > procedure Relink (Ptr: in out Pointer; E: aliased in out Element) is > begin > Ptr.Ref := E'Access; > end Relink; > > A,B: aliased Element; > Ptr_A, Ptr_B: Pointer; > > begin > Ptr_A.Ref := A'Access; > Ptr_B.Ref := B'Access; > > Relink (Ptr_B, A); > End; > > Am I misunderstanding this? I get the feeling that this is specifically > intended for function and their return objects specifically (kind of as it > was before), but this isn't very clear from what I read.. It's specifically related to certain functions (not all functions). As Steve wrote: > Dynamic semantics: > > The current RM wording distinguishes between a function and > other callable entities (e.g., procedures, entries) in defining > the accessibility level of an explicitly aliased parameter. > > Instead, we want to distinguish a function whose result > type requires (at runtime) passing in an accessibility level > parameter from other callable entities. Note that the details of > the rules to capture this distinction, whatever those details > are, have nothing to do with explicitly aliased parameters. **************************************************************** From: Randy Brukardt Sent: Monday, September 23, 2019 8:56 PM > There was some internal discussion within AdaCore a while back about > some possible minor changes to the accessibility rules for explicitly > aliased parameters. This is a description of those changes and their > motivation. No specific wording is proposed; at this point the goal is > only to determine whether it makes sense to produce wording for a more > specific proposal. > > Tuck believes that this proposal reflects the original intent of the > language designers back when explicitly aliased parameters were added > to the language and so this is just a matter of correcting the RM to > reflect that original intent. > In any case, it seems that it would simplify implementations without > costing users any useful functionality. Tucker is mistaken. This is not close to the intent of the rules for explicitly aliased parameters. The intent of the rules (which I mostly designed with some input from Tucker to check sanity) was: * It is *never* necessary to pass any dynamic accessibility with or for explicitly aliased parameters. This is accomplished by a variety of rules: (1) We make any needed dynamic checks at the call site, by requiring that the actual object for an explicitly aliased parameter of a function has the accessibility of the function result. (2) For all purposes except the comparision against the accessibility of the function result, an explicitly aliased parameter acts the same as a normal parameter (that is, it has local accessibility). (3) For the comparision against the accessibility of the function result, no check is ever needed (it was previously checked). This is both statically and dynamically (the static part is needed as it would necessarily fail without a special rule). ----------- Note that (2) means that procedure parameters never have any special accessibility. The wording used "inside of a return statement" to describe case (3), since there wasn't a way in 2005 to talk about the accessibility of a function result. At the time the wording was designed for Ada 2005, SAOAATs had static accessibility, so the rule of (2) would ban the use of Explicitly-Aliased-Parameter'Access as the initialization of a SAOAAT. Changing SAOAATs to have dynamic accessibility breaks this property. This is a problem with SAOAATs however, and not with the original intent -- this is fixable by banning the offending SAOAATs inside of extended return statements. Obviously, there could be other problems with the original wording -- it's accessibility after all, so one can pretty much assume there is some problem. But I'm not aware of any. ----------- The rules that Tucker proposed have the very nasty effect of changing the accessibility of an explicitly aliased parameter when the type of the function return is changed -- even if the change is to a private component of the type. It also cannot be a static rule, since the need for dynamic accessibility can be hidden inside of a return type (any use of an access discriminant on a component triggers this requirement, even inside of private components). That means that call-site accessibility checks always have to be required (for function parameters). It doesn't help to imply that some other rule is possible. I don't see any advantage to using dynamic accessibility for explicitly aliased parameters in any context. It certainly isn't necessary to support any of their intended uses. I'll need to see some examples of why that is necessary before I foist any such overhead on any program. I could see rewording with current rules to use "master of the call" (a term that didn't exist when these rules were written) in such a way to avoid having to talk about being within/without a return statement. Other changes don't seem to be required (pending some compelling example of an unintended usage). This topic is clearly not thought out at all, since the entire proposal is built on a serious misunderstanding of the intent of the rules. It's unfortunate that no one asked me about this before proposing a seriously flawed complete replacement of the rules which adds serious dynamic overhead. Much more discussion is required. **************************************************************** From: Richard Wai Sent: Monday, September 23, 2019 10:46 PM ... > * It is *never* necessary to pass any dynamic accessibility with or > for explicitly aliased parameters. This is accomplished by a variety of rules: > > (1) We make any needed dynamic checks at the call site, by requiring that > the actual object for an explicitly aliased parameter of a function has > the accessibility of the function result. > (2) For all purposes except the comparision against the accessibility > of the function result, an explicitly aliased parameter acts the same as a > normal parameter (that is, it has local accessibility). > (3) For the comparision against the accessibility of the function > result, no check is ever needed (it was previously checked). This is both > statically and dynamically (the static part is needed as it would > necessarily fail without a special rule). > > ----------- Perfectly stated. The whole idea of accessibility levels passing into subprograms dynamically seems like a pretty dangerous idea, even if it is supposedly transparent to the user. I was a bit thrown off by why the accessibility check would happen in the subprogram body itself. I do think the RM could make the role and purpose of explicitly aliased parameters a little bit more clear to the average user, for what it's worth. But this proposal seems to be more about allowing awkward implementations. > This topic is clearly not thought out at all, since the entire > proposal is built on a serious misunderstanding of the intent of the rules. > It's unfortunate that no one asked me about this before proposing a > seriously flawed complete replacement of the rules which adds serious > dynamic overhead. Much more discussion is required. I'm with you there.. **************************************************************** From: Tucker Taft Sent: Thursday, September 26, 2019 3:43 PM I suspect we are in violent agreement here. Steve's initial attempt introduced dynamic checks even in cases where there was nothing being passed in for other reasons. I was trying to eliminate any extra overhead, so there would only be dynamic checks when we already had the information available. If we can go further and eliminate the dynamic checks completely at the point of the return statement, I am all in favor. **************************************************************** From: Randy Brukardt Sent: Tuesday, October 1, 2019 6:27 PM Attached is the AI I came up with. Not sure if Steve has some examples where it would be important to have the "right" dynamic level, but I assumed those don't exist and wrote the simplest possible change. ****************************************************************