!standard 13.14(15) 17-04-20 AI12-0186-1/05 !class binding interpretation 16-10-08 !status Amendment 1-2012 16-11-10 !status ARG Approved 7-0-2 16-10-09 !status work item 16-04-21 !status received 16-01-09 !priority Low !difficulty Hard !qualifier Clarification !subject Profile freezing for the Access attribute !summary Using the access attribute does not freeze the profile of the associated access type (nor of the subprogram denoted by the prefix); that only happens upon a call of a value of the access type, use as a generic actual parameter of an instance, the occurrence of a body, or at the end of the declarative part. !question Consider: procedure Proc (It : Blob); type Ptr is access procedure (It : Blob); Link : Ptr := Proc'access; The declaration freezes Ptr, and the expression freezes Proc, but NOT its profile. However, freezing an entity means (intuitively) that the entity is usable at that point. An access_to_subrogram with an unknown profile is certainly not usable yet. 13.14(15) says that any names in a full_type_declaration are frozen when the type is. Thus, in the above example, the declaration of Link freezes Ptr, and Ptr freezes Blob (because it is a name appearing in a full_type_declaration). This effectively freezes the profile, since everything in it is frozen. However, a couple of ACATS tests fail when this interpretation is implemented. Is our compiler or the ACATS tests correct? (The ACATS tests.) !recommendation 13.14 freezes profiles only in a few places: * "General" freezing points like the occurrence of a body or the end of a declarative part. (At these places, everything is frozen.) - 13.14(3/5) and others. * Calls to a function - 13.14(10.1/4) and 13.14(8.1/3). * When a subprogram is used as an actual parameter to a generic instantation - 13.14(10.2/4). A reference to an Access attribute was definitely not intended to be a place where the profile of a subprogram is frozen. Unfortunately, the wording of 13.14(15) is somewhat unclear. The original intent was that "names" referred to object names and other names that appear within expressions, but not subtype_marks except those that were explicitly enumerated (parent subtype, component subtype, etc.). We agree the wording should be clarified. !wording Modify 13.14(15): At the place where a subtype is frozen, its type is frozen. At the place where a type is frozen, any expressions or names within the full type definition cause freezing{, other than those that occur within an access_type_definition or an access_definition}; the first subtype, and any component subtypes, index subtypes, and parent subtype of the type are frozen as well. For a specific tagged type, the corresponding class-wide type is frozen as well. For a class-wide type, the corresponding specific type is frozen as well. !discussion The intent of 13.14(15) was that the only subtypes that were frozen as a side-effect of freezing a type were enumerated directly (parent subtype, component subtypes, etc.). But the term "name" is very general, and names appear within subtype_marks in particular. So we clarify that any names or expressions occurring within an access[_type]_definition do not cause freezing even if they appear within the full type definition of a type being frozen. Note that the designated subtype, and the designated profile, are frozen at a later point, as explained in 13.14(13) and 13.14(10.1/4) respectively. One implication of this is that 'Access does not freeze the profile of the corresponding access-to-subprogram type. There clearly is some implementation impact from being able to use the Access attribute for a subprogram with an unfrozen profile. In particular, if a wrapper is needed, that will have to be deferred (at least) until the freezing point of the profile. However, Ada 2012 already has similar requirements for incomplete types (which are never frozen, confirmed by AI12-0155-1). For a Taft-amendment type, the real profile of a subprogram may not be known until the body is compiled, long after the specification is compiled. For instance: package P1 is type T is private; ... private type Taft; type T is access Taft; type Ptr is access procedure (It : Taft); -- Legal, even in Ada 95. package Inner is -- Make the operation non-primitive. procedure Proc (It : Taft); -- Legal in Ada 2012. end Inner; Link : Ptr := Proc'Access; -- Legal. end P1; So long as Link is called after the completion of Taft in the body, this is all legal. A compiler has to be able to generate Proc'Access without knowing anything about the representation of Taft. (If Taft is a tagged incomplete type, a child package could even call Link without knowing the exact representation of Taft.) Since similar cases already exist, there doesn't seem to be any need to adopt an incompatible rule to have Proc'Access freeze the profile. ----- We briefly were concerned that expressions in constraints of designated subtypes would not be handled by the revised wording. Specifically, consider: package P is X : constant Integer; type A is access Rec(3*X); -- Elaborates X, must be frozen so it is illegal. private ... end P; The new 13.14(15) wording does not freeze X in this case (X occurs in an access_type_definition). However, that doesn't matter, as 13.14(8) says that a nonstatic expression causes freezing where it occurs. Thus X is frozen by 13.14(11), as part of the type declaration, regardless of the wording of 13.14(15). !corrigendum 13.14(15) @drepl @xbullets within the full type definition cause freezing; the first subtype, and any component subtypes, index subtypes, and parent subtype of the type are frozen as well. For a specific tagged type, the corresponding class-wide type is frozen as well. For a class-wide type, the corresponding specific type is frozen as well.> @dby @xbullets within the full type definition cause freezing, other than those that occur within an @fa or an @fa; the first subtype, and any component subtypes, index subtypes, and parent subtype of the type are frozen as well. For a specific tagged type, the corresponding class-wide type is frozen as well. For a class-wide type, the corresponding specific type is frozen as well.> !ASIS No ASIS effect. !ACATS test A fairly low priority ACATS C-Test is needed to check examples like that in the question and discussion. !appendix From: Edmond Schonberg Sent: Saturday, January 9, 2016 4:42 PM A propos of which ... [split from a different e-mail thread] we are having troubles implementing properly the old AI05-019. The specific example is the declaration for an object to subprogram: procedure Proc (It : Blob); type Ptr is access procedure (It : Blob); Link : Ptr := Proc’access; The declaration freezes Ptr, and the expression freezes Proc, but NOT its profile. Now freezing an entity means (intuitively) that the entity is usable at that point. An access_to_subrogram with an unknown profile is certainly not usable yet. The GNAT backend has always assumed that when creating that object the full profile is available (i.e. its parameter types are frozen) and crashes or misbehaves if this is not the case. Is this is a gap in the heart of darkness (13.14) , or are we misleading AI0-019? A couple of ACATS tests trigger additional errors if subprogram profiles are frozen when an Access reference attribute appears in an object declaration. **************************************************************** From: Edmond Schonberg Sent: Monday, January 11, 2016 9:41 AM This may be so painfully obvious that people were too embarrassed to answer. I would still like some comment or confirmation: does the declaration of Link freeze type Blob? **************************************************************** From: Tucker Taft Sent: Monday, January 11, 2016 11:59 AM Not according to 13.14. The only things that freeze profiles are the "general" freezing points, a function call, and a generic instantiation. I believe the freezing should be deferred until you make a call on a dereference of an object of type Ptr. In other words, when you make a function call, you freeze the profile, whether it comes from a function declaration, or from an access-to-function type. Access-to-procedure profiles would only be frozen by "general" freezing points, and presumably by generic instantiations. Some sort of AI seems needed to clarify this! **************************************************************** From: Edmond Schonberg Sent: Monday, January 11, 2016 12:23 PM > Not according to 13.14. The only things that freeze profiles are the > "general" freezing points, a function call, and a generic instantiation. and an object declaration (13.14 (6), That certainly freezes the type of the object. Then 13.14 (16) states that all names in the type definition are frozen. So I’m not convinced. **************************************************************** From: Gary Dismukes Sent: Monday, January 11, 2016 1:07 PM (Presumably you mean 13.14(15).) The "names" referred to there don't include things like subtype_marks, but refers to names in expressions. Note that component subtypes are called out separately in that rule. So this doesn't include parameter subtypes of a profile in the access-to-subprogram type. **************************************************************** From: Edmond Schonberg Sent: Monday, January 11, 2016 1:18 PM > (Presumably you mean 13.14(15).) The "names" referred to there don't > include things like subtype_marks, but refers to names in expressions. Could be the intent, but I certainly cannot deduce it from the text. A name is something that denotes an entity, and that certainly includes subtype_marks. Why are they excluded by this paragraph? **************************************************************** From: Gary Dismukes Sent: Monday, January 11, 2016 1:34 PM Umm, so that subtypes in profiles wouldn't be frozen? ;-) Let's just say that I think it's the intent that those subtypes aren't frozen by declaration of an object of the access type. I believe that the "expressions and names" of the rule refers to top-level syntactic instances of those things, and the "name" of a subtype_mark is buried deeper and doesn't count. Perhaps the rule could be clearer (assuming that's the intent). Let's see what other think. **************************************************************** From: Tucker Taft Sent: Monday, January 11, 2016 2:21 PM I agree. 13.14(15) says: "At the place where a subtype is frozen, its type is frozen. At the place where a type is frozen, any expressions or names within the full_type_definition cause freezing; the first subtype, and any component subtypes, index subtypes, and parent subtype of the type are frozen as well. For a specific tagged type, the corresponding class-wide type is frozen as well. For a class-wide type, the corresponding specific type is frozen as well." I believe the use of the term "name" is overly general here, and should not include names that are subtype_marks. Otherwise, the discussion about first subtype, component subtypes, index subtypes, etc. would be largely redundant. It should probably be "names that denote objects or subprograms" ... **************************************************************** From: Edmond Schonberg Sent: Monday, January 11, 2016 2:34 PM Let us say that as a justification, “otherwise this other line would be redundant” is not terribly compelling. In any case we’ll have to rethink the implementation of freezing for access_to_subprograms in GNAT. **************************************************************** From: Randy Brukardt Sent: Thursday, April 21, 2016 7:04 PM I'm trying to make sense of this discussion so I can create an AI. I don't mind the "otherwise this line would be redundant" justification, as we try hard to avoid redundant text in the Standard, and also try to mark anything that is intentionally redundant. But I can do better: AARM 13.14(15.b) says "Freezing an access type does not freeze its designated subtype." If we used Ed's interpretation of 13.14(15), there is no way that could be true, since there is always a "name" within the subtype_mark of the designated type: type Ptr is access Blob; P : Ptr; -- Does not freeze Blob by 13.14(15.b) Since Blob is not frozen here (to make the clear intent of 15.b True), 13.14(15) cannot be talking about the "name" within the "subtype_mark" Blob. QED. Tucker suggested trying to reword the rule to make it clearer that "name" isn't talking about names in subtype_marks. Specifically: > It should probably be "names that denote objects or subprograms" ... I think his rewording is dangerous, as it potentially leaves a hole for other kinds of entities (exceptions? named numbers? etc.) I think we'd be better off with a To Be Honest note suggesting that the "expressions or names within the full_type_declaration" is speaking syntactically; we're not looking inside of other entities appearing in the type declaration (like subtype_marks and subtype_indications). If it turns out not to be right either, we at least won't have broken anything (AARM Notes can always be ignored, and are much more easily fixed than RM wording.) This wording has been around since (at least) Ada 9X version 3.0 (and a version of the rule is in version 2.0 as well), and I don't remember anyone challenging it before. Doesn't seem critical to change. --- I've also been mulling the actual problem. It seems to me that it is related (in a sense) to incomplete types (there's not much difference between an unfrozen type and an incomplete type, which never is frozen). One can construct a similar case with Taft-Amendment types: package P1 is type T is private; ... private type Taft is tagged; type T is access Taft; type Ptr is access procedure (It : Taft); -- Legal, even in Ada 95. package Inner is -- Make the operation non-primitive. procedure Proc (It : Taft); -- Legal in Ada 2012. end Inner; Link : Ptr := Proc'Access; -- Legal. end P1; The declaration of Link doesn't violate any freezing rules, and it doesn't violate any accessibility or conformance rules, so it must be legal. And one could call it in a child package that has no knowledge of the type (even worse than the freezing case). An actual call will (outside of incomplete types) freeze the types of the parameters, so one never has to generate a call without freezing. But one might need to defer a wrapper until the end of the unit (or when the profile is frozen; usually I find the former easier, but YMMV): package P2 is type Blob is range 0 .. 100; function Func (It : Blob) return Natural; type Ptr is access function (It : Blob) return Natural; Link : Ptr := Func'Access; -- Does not freeze the profile of Func, thus does not freeze Blob. for Blob'Size use 8; -- An evil rep. clause. Var : Natural := Link(10); -- Freezes the profile of Ptr, thus freezes Blob. end P2; If Func'Access needs a wrapper of some sort, it can't be generated until the profile is frozen, and that doesn't happen until Var is declared. The explicit use of Func'Access just has to be a label of some sort. (I generally just do deferred things at the end of the unit, as it doesn't matter where the actual code lives, since it is accessed by the label anyway. Once you have to defer it a little, it doesn't matter how much it gets deferred.) --- Anyway, I've concluded that there isn't any real problem here, at least not any NEW problem, so I'm going to write this up as a Ramification (with a To Be Honest note) and you can throw bricks in Pisa. **************************************************************** From: Randy Brukardt Sent: Thursday, April 21, 2016 8:08 PM The proposed TBH uses Gary's explanation that "name" and "expression" in this rule are talking about direct syntax and not about names or expressions that happen to occur in other constructs that make up the full_type_declaration. I'm happy to take credit for the AI if it is correct, but if there is something wrong with Gary's explanation then that's all his idea. ;-) :-) **************************************************************** From: Tucker Taft Sent: Thursday, April 21, 2016 9:59 PM > ... Anyway, I've concluded that there isn't any real problem here, at > least not any NEW problem, so I'm going to write this up as a > Ramification (with a To Be Honest note) and you can throw bricks in Pisa. In Pisa it might be more appropriate to drop them from the leaning tower and see which lands first... ;-) **************************************************************** From: Tucker Taft Sent: Tuesday, October 4, 2016 9:42 PM Here is an update. [This is version /02 of the AI - Editor.] It is surprising that paragraph 13.14(15) could have been so misleading for so long, as far as what happens when you freeze an access type. The answer is that the names and expressions inside the access[_type]_defininition do not cause freezing. That only happens when the designated subtype/profile is frozen. **************************************************************** From: Randy Brukardt Sent: Wednesday, October 5, 2016 6:24 PM Procedural: This AI is no longer a ramification if it changes normative wording in the Standard. (Ramifications can only change notes, examples, and the AARM.) It needs to be reclassified as a Binding Interpretation. **************************************************************** From: Tucker Taft Sent: Wednesday, October 5, 2016 8:22 PM Sorry. Forgot about that part. It might be considered a clarification I suppose, though perhaps there is no such classification. **************************************************************** From: Randy Brukardt Sent: Wednesday, October 5, 2016 8:55 PM "Clarification" is one of the three sub-categories of Binding Interpretation. **************************************************************** From: Tucker Taft Sent: Saturday, October 8, 2016 9:00 PM I had to split out access-to-object and access-to-subprogram, and be careful how I talked about the subtype_mark "used in specifying" the designated_subtype (since in some cases it is part of a subtype_indication, and in others it is used directly). Hence,... Modify 13.14(15) as follows: At the place where a subtype is frozen, its type is frozen. At the place where a type is frozen, any expressions or names within the full type definition cause freezing{, other than the name that is the subtype_mark used in specifying the designated subtype in an access-to-object type definition, or expressions or names that appear within the designated profile of an access-to-subprogram type definition}; the first subtype, and any component subtypes, index subtypes, and parent subtype of the type are frozen as well. For a specific tagged type, the corresponding class-wide type is frozen as well. For a class-wide type, the corresponding specific type is frozen as well. ****************************************************************