!standard 3.10.2(3/2) 20-12-15 AI12-0406-1/04 !standard 3.10.2(18) !standard 3.10.2(19/3) !standard 3.10.2(19.1/3) !standard 7.6.1(3/2) !class binding interpretation 20-11-20 !status Amendment 1-2012 20-12-09 !status ARG Approved 15-0-0 20-12-09 !status work item 20-11-20 !status received 20-11-20 !priority Low !difficulty Easy !qualifier Clarification !subject Clarifying static accessibility !summary The term "master construct" is introduced to clarify the static meaning of master (as used to define the "statically deeper" relationship). The statically deeper relationship does not apply to types declared in generic formal packages. !question (1) While researching another question, issues were raised with the use of masters in the definition of statically deeper, used for accessibility Legality Rules. "Master" is defined to be a dynamic concept, being the execution of certain constructs (see 7.6.1(3/2)). Statically deeper is defined in terms of this dynamic concept, something that is noted in the AARM as being dubious. One effect of this is that a construct defined in a generic unit can never have a master, since a generic unit is never executed (an instance of a generic unit can be executed, but that's a different unit). As such, the language, strictly speaking, does not define any static accessibility checks in generic units. This does not match typical practice nor intuition. Should these definitions be reworded? (Yes.) (2) Types declared in a generic formal package act much like generic formal types themselves. However, the "statically deeper" rules do not treat these in the same way as generic formal types. This means that operations using such types can be rejected even when there is no problem -- see !example for such a case. Should this be corrected? (Yes.) !recommendation (See Summary.) !wording The changes to 3.10.2(19/3-19.1/3) are needed for question (2), the other changes are needed for question (1). Modify 3.10.2(3/2): The accessibility rules, which prevent dangling references, are written in terms of /accessibility levels/, which reflect the run-time nesting of /masters/. As explained in 7.6.1, a master is the execution of a certain construct {(called a /master construct/)}, such as a subprogram_body. An accessibility level is ... Modify 3.10.2(18): For a master {construct} that is statically nested within another master {construct}, the accessibility level of the inner master {construct} is statically deeper than that of the outer master {construct}. Delete AARM 3.10.2(18.a). [We're now talking about constructs.] Replace 3.10.2(19/3-19.1/3): [Note: The third paragraph here comes from AI12-0392-1] The statically deeper relationship does not apply to the accessibility level of the anonymous type of an access parameter specifying an access-to-object type nor does it apply to a descendant of a generic formal type; that is, such an accessibility level is not considered to be statically deeper, nor statically shallower, than any other. The statically deeper relationship does not apply to the accessibility level of the type of a stand-alone object of an anonymous access-to-object type; that is, such an accessibility level is not considered to be statically deeper, nor statically shallower, than any other. The statically deeper relationship does not apply to the accessibility level of a raise_expression; that is, such an accessibility level is not considered to be statically deeper, nor statically shallower, than any other. with: The statically deeper relationship does not apply to the accessibility level of the following: * the anonymous type of an access parameter specifying an access-to-object type; * the type of a stand-alone object of an anonymous access-to-object type; * a raise_expression; * a descendant of a generic formal type; * a descendant of a type declared in a generic formal package. That is, such an accessibility level is not considered to be statically deeper, nor statically shallower, than any other. Modify 7.6.1(3/2): After execution of a construct or entity is complete, it is *left*, meaning that execution continues with the next action, as defined for the execution that is taking place. Leaving an execution happens immediately after its completion, except in the case of {the execution of} a *master {construct}*: [the execution of] a body other than a package_body; [the execution of] a statement; or [the evaluation of] an expression, function_call, or range that is not part of an enclosing expression, function_call, range, or simple_statement other than a simple_return_statement. {The term *master* by itself refers to the execution of a master construct.} A master is finalized after it is complete, and before it is left. Revise the existing (from AI12-0330-1) glossary entry: Master: A master is the execution of a master construct. Each object and task is associated with a master. When a master is left, associated tasks are awaited and associated objects. Add a glossary entry: Master construct: A master construct is one of certain executable constructs listed in 7.6.1. Execution of a master construct is a master, with which objects and tasks are associated for the purposes of waiting and finalization. !discussion (1) AARM 3.10.2(18.a) admits that talking about masters in a Legality Rule is bogus; by introducing the term "master constructs" we eliminate this problem. We do not expect this rewording to require any change to implementations. Existing ACATS tests and implementations do make static accessibility checks in generic units; we're just making the wording in the Standard match the common sense definition of static nesting -- and avoid talking about a compile-time interpretation of an execution. (2) 3.10.2(19/3) says that the statically deeper relationship does not apply to generic formal types, while 3.10.2(20) says that a generic package body is assumed instantiated at the level it is declared. The reason for the difference is that a generic unit can be instantiated at the same level or a deeper level; it cannot be instantiated at an outer level (as it is not visible). Thus, we can assume that the level is at least that of the declaration and make appropriate static checks in that case. This is essentially an "assume-the-best" rule with dynamic checks (and rechecking in the specification of the instance) used when the best isn't true. However, the actual for a generic formal type parameter can be of any level up to the level of the instance. In particular, a type declared at library-level can be passed to an instance at a very deep level. Thus, there is no useful assumption about the level of a formal type that can be made, and therefore we say that no static checks can be made for it. Dynamic checks (and rechecking in the specification of the instance) are used in all cases to avoid problems. Types declared in a generic formal package act much like those which are directly generic formal types. In particular, an instance declared at an outer level can be the actual for a formal package; and thus types declared in formal packages should be treated in the same way as generic formal types. !example The following example is a distillation of an AdaCore customer problem report. procedure Aaa is type Root is tagged null record; type Ref is access Root'Class; generic package G1 is type Ext is new Root with null record; end G1; generic with package I1 is new G1 (<>); procedure G2; procedure G2 is Ptr : Ref := new I1.Ext; -- (1) begin null; end G2; -- package My_I1 is new G1; -- procedure My_I2 is new G2 (My_I1); begin -- My_I2; null; end Aaa; The Ada 2012 rules make the allocator at (1) illegal, by 4.8(5.2/3). With the wording change proposed by this AI, (1) becomes legal as the "statically deeper" relationship does not apply. A dynamic check is still required at (1), in case the instance of G2 is nested more than type Ref. !corrigendum 3.10.2(3/2) @drepl The accessibility rules, which prevent dangling references, are written in terms of @i, which reflect the run-time nesting of @i. As explained in 7.6.1, a master is the execution of a certain construct, such as a @fa. An accessibility level is @i another if it is more deeply nested at run time. For example, an object declared local to a called subprogram has a deeper accessibility level than an object declared local to the calling subprogram. The accessibility rules for access types require that the accessibility level of an object designated by an access value be no deeper than that of the access type. This ensures that the object will live at least as long as the access type, which in turn ensures that the access value cannot later designate an object that no longer exists. The Unchecked_Access attribute may be used to circumvent the accessibility rules. @dby The accessibility rules, which prevent dangling references, are written in terms of @i, which reflect the run-time nesting of @i. As explained in 7.6.1, a master is the execution of a certain construct (called a @i), such as a @fa. An accessibility level is @i another if it is more deeply nested at run time. For example, an object declared local to a called subprogram has a deeper accessibility level than an object declared local to the calling subprogram. The accessibility rules for access types require that the accessibility level of an object designated by an access value be no deeper than that of the access type. This ensures that the object will live at least as long as the access type, which in turn ensures that the access value cannot later designate an object that no longer exists. The Unchecked_Access attribute may be used to circumvent the accessibility rules. !corrigendum 3.10.2(18) @drepl @xbullet @dby @xbullet !corrigendum 3.10.2(19/3) @drepl @xbullet @dby @xbullet !corrigendum 3.10.2(19.1/3) @drepl @xbullet @dby @xinbull @xinbull @xinbull;> @xinbull @xinbull @xindent !corrigendum 7.6.1(3/2) @drepl After execution of a construct or entity is complete, it is @i, meaning that execution continues with the next action, as defined for the execution that is taking place. Leaving an execution happens immediately after its completion, except in the case of a @i: the execution of a body other than a @fa; the execution of a @fa; or the evaluation of an @fa, @fa, or @fa that is not part of an enclosing @fa, @fa, @fa, or @fa other than a @fa. A master is finalized after it is complete, and before it is left. @dby After execution of a construct or entity is complete, it is @i, meaning that execution continues with the next action, as defined for the execution that is taking place. Leaving an execution happens immediately after its completion, except in the case of the execution of a @i: a body other than a @fa; a @fa; or an @fa, @fa, or @fa that is not part of an enclosing @fa, @fa, @fa, or @fa other than a @fa. The term @i by itself refers to the execution of a master construct. A master is finalized after it is complete, and before it is left. !ASIS No ASIS effect. !ACATS test No (new) tests should be needed for question (1). For question (2), a C-Test like the example is needed to check that types in formal packages are treated properly. This test would include a (simple) case where the dynamic check would fail. !appendix ****************************************************************