!standard 03.11 (10) 00-04-12 AI95-00064/09 !standard 03.11.01 (01) !standard 08.05.04 (08) !class binding interpretation 95-07-06 !status Corrigendum 2000 99-05-24 !status WG9 approved (8-0-0) 97-07-04 !status ARG approved (9-0-0) 97-04-11 !status work item (letter ballot was 10-1-1) 96-10-03 !status work item 96-06-14 (returned to ARG by WG9) !status ARG approved 8-0-2 (by letter ballot) 96-06-05 !status ARG approved (subject to editorial review) 8-0-2 95-11-01 !status received 95-07-06 !reference AI95-00135 !priority High !difficulty Hard !qualifier Omission !subject Elaboration checks for renamings-as-body !summary An elaboration check is performed for a call to a subprogram whose body is given as a renaming-as-body. This check fails if the renaming-as-body has not yet been elaborated. (As usual, an elaboration check is also performed for the renamed subprogram, and fails if *its* body has not yet been elaborated.) !question 3.11(10) indicates that an elaboration check is required only when a subprogram has an explicit body that is a subprogram_body. However, when a renaming declaration is used as a body, it is possible for the elaboration of the renaming declaration to require the evaluation of a name, such as X.all, that implies some sort of elaboration check should be performed. For example: function F return Integer; type Pointer_To_Func is access function return Integer; X : Pointer_To_Func := Q'Access; -- Presume Q already elaborated Y : Integer := F; -- We need some sort of elaboration check .... Z : Pointer_To_Func := X; function F return Integer renames Z.all; In the above, clearly we need to wait until the expression "Z.all" is evaluated before F can be safely called. However, it is not clear that any check for this is required by 3.11(10). By the way, where is "body" defined? It presumably includes entry body, and perhaps renaming-as-body. However, only the syntactic entity BODY is defined (in 3.11). Where is the unbolded term "body" defined? !recommendation (See summary.) !wording Define the term "body" to include the syntactic category body, plus entry_body, plus renaming-as-body, in 3.11.1(1). Change "subprogram_body" to "body" in 3.11(10). Add a paragraph before 8.5.4(8) to define the run-time semantics of renamings-as-body: For a call to a subprogram whose body is given as a renaming-as-body, the execution of the renaming-as-body is equivalent to the execution of a subprogram_body that simply calls the renamed subprogram with the same parameters. Change the freezing rule in 13.14(3) to exclude renaming-as-body from the freezing rules. !discussion Since the elaboration of a renaming-as-body may evaluate expressions, it is clearly necessary that this elaboration be performed before calling the subprogram. Therefore, an elaboration check should be done on a subprogram whose body is a renaming-as-body, not just when the body is a subprogram_body. It seems that the right model for renaming-as-body that occurs after the subprogram is frozen should be that of a wrapper subprogram, with its own elaboration "bit." Taken together, these rules imply that when calling a subprogram whose body is a renaming-as-body, a check will be made that the renaming-as-body has been elaborated, and also that the body of the renamed subprogram has been elaborated. Furthermore, if the renamed subprogram is in turn completed by *another* renaming-as-body, the body of that third subprogram will also be checked; the rule is transitive. See AI95-00135 for a discussion of circularities involving renamings-as-body. This issue also adds the missing definition of lower-case "body". This change makes a renaming-as-body a body. However, doing so triggers the freezing rule 13.14(3): "A noninstance body other than a renaming-as-body causes freezing of each entity declared before it within the same declarative_part." It clearly was the intent of the designers of the language that renaming-as-body not freeze (otherwise the second sentence of 8.5.4(5) could never be true), and existing compilers do not freeze when a renaming-as-body is encountered. We do not want to change this behavior, so we add an exception to 13.14(3). !corrigendum 3.11(10) @drepl @xbullet is already elaborated. This check and the evaluations of any actual parameters of the call are done in an arbitrary order.> @dby @xbullet !corrigendum 3.11.01(1) @drepl Declarations sometimes come in two parts. A declaration that requires a second part is said to @i. The second part is called the @i of the declaration (and of the entity declared), and is either another declaration, a body, or a @fa. @dby Declarations sometimes come in two parts. A declaration that requires a second part is said to @i. The second part is called the @i of the declaration (and of the entity declared), and is either another declaration, a body, or a @fa. A @i is a @fa, an @fa, or a renaming-as-body (see 8.5.4). !corrigendum 8.05.04(8) @dinsb For a call on a renaming of a dispatching subprogram that is overridden, if the overriding occurred before the renaming, then the body executed is that of the overriding declaration, even if the overriding declaration is not visible at the place of the renaming; otherwise, the inherited or predefined subprogram is called. @dinst For a call to a subprogram whose body is given as a renaming-as-body, the execution of the renaming-as-body is equivalent to the execution of a @fa that simply calls the renamed subprogram with its formal parameters as the actual parameters and, if a function, returns the value of the call. !corrigendum 13.14(3) @drepl The end of a @fa, @fa, or a declaration of a library package or generic library package, causes @i of each entity declared within it, except for incomplete types. A noninstance body causes freezing of each entity declared before it within the same @fa. @dby The end of a @fa, @fa, or a declaration of a library package or generic library package, causes @i of each entity declared within it, except for incomplete types. A noninstance body other than a renaming-as-body causes freezing of each entity declared before it within the same @fa. !ACATS test ACATS test C854002 was constructed to check this ruling, and checks cases similiar to the example in the question. !appendix !section 3.11(9) !section 8.5.4(1) !subject Renaming-as-body and elaboration !reference RM95 3.11(9,10) !reference RM95 8.5.4(1) !from Tucker Taft 95-07-05 !reference as: 95-5208.a Tucker Taft 95-7-5>> !discussion In 3.11(10), it indicates that an elaboration check is only required when a subprogram has an explicit body that is a subprogram_body. However, when a renaming declaration is used as a body, it is possible for the elaboration of the renaming declaration to require the evaluation of a name, such as X.all, that implies some sort of elaboration check should be performed. For example: function F return Integer; type Pointer_To_Func is access function return Integer; X : Pointer_To_Func := Q'Access; -- Presume Q already elaborated Y : Integer := F; -- We need some sort of elaboration check .... Z : Pointer_To_Func := X; function F return Integer renames Z.all; In the above, clearly we need to wait until "Z.all" is elaborated before calling F. However, it is not clear that any check for this is required by 3.11(10). It seems that the right model for renaming-as-body that occurs after the subprogram is frozen should be that of a wrapper subprogram, with its own elaboration "bit." By the way, where is "body" defined? It presumably includes entry body, and perhaps renaming-as-body. However, only the syntactic entity BODY is defined (in 3.11). Where is the unbolded term "body" defined? -Tuck **************************************************************** !section 03.11(09) !subject Call for letter ballot on AI95-00064 !reference AI95-00064/01 !from Norman Cohen 96-04-29 !reference 96-5524.a Norman H. Cohen 96-4-29>> !discussion I call for a letter ballot on AI-64 because I believe the elaboration check needs to be defined more precisely: Presumably, it is checked both that the renaming declaration has been elaborated and that the body of the renamed subprogram has been elaborated. (In addition, the AI should make it obvious that this check is performed at the time of a call.) I suggest that the !recommendation be rewritten in language that parallels 3.11(10) and 3.11(14): For a call to a (non-protected) subprogram that has a renaming-as-body, a check is made that the renaming declaration has already been elaborated, and that the body of the subprogram named in the renaming declaration has already been elaborated. This check and the evaluations of any actual parameters of the call are done in an arbitrary order. The exception Program_Error is raised if this check fails. (Perhaps just the first sentence will suffice as the !summary.) Can this be considered an editorial correction, and a revised version recirculated for letter ballot, before the next meeting? **************************************************************** !section 3.11(09) !subject Call for letter ballot on AI95-00064 !reference 03.11(09) !reference AI95-00064/01 !reference 96-5524.a Norman Cohen 96-04-29 !reference 96-5543.a Robert A Duff 96-5-8>> !discussion Norman says: > I call for a letter ballot on AI-64 because I believe the elaboration > check needs to be defined more precisely: Presumably, it is checked > both that the renaming declaration has been elaborated and that the > body of the renamed subprogram has been elaborated. (In addition, the > AI should make it obvious that this check is performed at the time of a > call.) > > I suggest that the !recommendation be rewritten in > language that parallels 3.11(10) and 3.11(14): > > For a call to a (non-protected) subprogram that has a > renaming-as-body, a check is made that the renaming declaration has > already been elaborated, and that the body of the subprogram named in > the renaming declaration has already been elaborated. This check and > the evaluations of any actual parameters of the call are done in an > arbitrary order. The exception Program_Error is raised if this check > fails. > > (Perhaps just the first sentence will suffice as the !summary.) I agree with Norm's complaint. However, I think the above wording fails to handle the transitive cases. If the body of P renames Q, and the body of Q renames R, and the body of R renames S, then we need to check that the bodies of all of P, Q, R, and S have been elaborated. The above wording only checks P and Q. I think a better solution is to add something like this to the !wording section: Add a paragraph before 8.5.4(8) to define the run-time semantics of renamings-as-body: The execution of a renaming-as-body is equivalent to the execution of a subprogram_body that simply calls the renamed subprogram with the same parameters. This makes the rule correctly transitive, and I think is more elegant anyway. > Can this be considered an editorial correction, and a revised version > recirculated for letter ballot, before the next meeting? Will do. By the way, I disagree that the !summary needs to be so precise. Everybody knows that elaboration checks are done at call sites, and the summary is supposed to be as simple as possible without being outright wrong. The !wording section, on the other hand, defines the precise rule (or it will, soon). (This is one AI that I thought was subtle enough that it deserved to have a wording section.) So, Norm, I suggest you read the new !wording when I send it out, and criticize *that* if you think it's still not right. - Bob **************************************************************** From: Erhard Ploedereder Sent: Monday, April 03, 2000 4:19 AM Dear ARG members that were not in Phoenix, On one of the TC items we ran into secondary technical problem. Rather than have you wait for the minutes, I want to solicit your opinion on the issue now. The wording change for the AI that resolves the elaboration question includes a renaming-as-body in the semantic category "body". However, noninstance bodies freeze all entities declared before them. We had a choice to make and we chose to explicitly exclude renaming-as-body from this freezing rule, largely because we did not want to mess with the presumed designers' intent that renames don't cause freezing. We noted, however, that such freezing would solve the circular renaming AI (and the taking of the convention from the renamed subprogram) trivially. Was our choice the right one ? If you believe that we should make renaming-as-body a cause for freezing, speak up now. **************************************************************** From: Robert Dewar Sent: Monday, April 03, 2000 8:41 AM This seems very wrong to me. Renaming-as-body should be semantically equivalent to the expanded body. Indeed on GNAT that's all it is. I suppose some glitch can be programmed into the implementation to make this a special case, but I would find this non-equivalence weird from a semantic point of view anyway. **************************************************************** From: Pascal Leroy Sent: Monday, April 03, 2000 9:07 AM I agree. If you think of maintenance it's likely that some bodies will need to be changed from a renaming-as-body to a true body (or vice-versa). This should be possible without affecting the legality of the code. The current rules already make sure that you can switch between a subunit and a proper body without trouble. I see no reason to use different rules for a renaming-as-body. Incidentally our compiler current does not consider that a renaming-as-body freezes, but changing that is a one-liner. **************************************************************** From: Ed Schonberg Sent: Monday, April 03, 2000 8:36 AM GNAT does not treat the renaming_as_body as a freezing point, we see no reason to change the rule, so we are happy with the exclusion. **************************************************************** From: Tucker Taft Sent: Monday, April 03, 2000 9:23 AM Renaming as body should not freeze in my opinion. I think it is important that you can declare several subprograms in the visible part, and then complete them in the private part via renaming, without losing the possibility that non-Ada conventions are carried over from the renamed entity. E.g.: type My_Int is private; function Plus(L, R : My_Int) return My_Int; function Minus(L, R : My_Int) return My_Int; private type My_Int is new Integer; function Plus(L, R : My_Int) return My_Int renames "+"; function Minus(L, R : My_Int) return My_Int renames "-"; This would not work if the first renaming-as-body froze things. **************************************************************** From: Robert Dewar Sent: Monday, April 03, 2000 9:35 AM Ed said <> OK, so implementation is not an issue in terms of GNAT. I still find it an odd difference, but am not willing to argue strongly against the majority conclusion :-) **************************************************************** From: Tucker Taft Sent: Monday, April 03, 2000 9:52 AM Robert Dewar wrote: > > This seems very wrong to me. Renaming-as-body should be semantically > equivalent to the expanded body. Indeed on GNAT that's all it is. I > suppose some glitch can be programmed into the implementation to make > this a special case, but I would find this non-equivalence weird from > a semantic point of view anyway. There are really two kinds of renaming-as-body. One which happens before the spec is frozen, and one after the spec is frozen. If the spec is not yet frozen, the renaming-as-body must be treated essentially like a deferred renaming-as-spec. The renaming-as-body is "seen" by all callers in this case, so you can really just redirect the call to the renamed routine. A renaming-as-body after the spec is frozen really has to produce an out-of-line body, even if it consists of only a "jump," unless you can play various link-time games with redirecting one link-name to bind to another (of course, that doesn't work if the renaming-as-body renames blah.all). So I suppose it would be OK if a renaming-as-body after the spec is frozen also froze other stuff, but I worry about incompatibilities where there are several "early" renaming-as-bodies with one "late" one interspersed, thereby converting all the remaining "early" renamings into late ones, and preventing non-Ada conventions. **************************************************************** From: Robert Dewar Sent: Monday, April 03, 2000 9:55 AM <> It is vaguely worrying that both Rational and GNAT are "wrong" here if we change it. What about other Ada 95 front ends? There is an argument for maintaining the current *behaviuor* if it is uniform. **************************************************************** From: Robert A Duff Sent: Monday, April 03, 2000 10:34 AM Pascal says: > If you think of maintenance it's likely that some bodies will need to be > changed from a renaming-as-body to a true body (or vice-versa). This > should be possible without affecting the legality of the code. Ahh, so we need to change the syntax rules to allow proper bodies in package specs. I wonder if Robert will insist that it be non-binding? ;-) ;-) During the 9X project, I had the same reaction as Robert: it's ugly for renaming-as-body to be anything but a short-hand. We discussed the issue of freezing, in particular. Tucker overruled me at the time, putting usefulness ahead of uniformity. There's no reason to change that decision now. **************************************************************** From: Pascal Leroy Sent: Tuesday, April 04, 2000 2:51 AM Yes, to be honest I keep forgetting that a renaming-as-body is legal in a spec. **************************************************************** From: Robert Dewar Sent: Wednesday, April 05, 2000 5:05 AM To be really honest, I did not know (or have forgotten) that it is legal in a spec. How odd .. seems a real mistake to me, precisely because it is not orthogonal to the idea of it simply being an abbreviation. A nice example of how simplicity at the definitional level (which is hopefully improved by this peculiar feature) is so different from simplicitly at the learning level (allowing this in a spec definitely makes it harder to understand at least to me). Reminds me of a : aliased string := "asef" and a : aliased string (1 .. 4) := "asef"; being different. Well I guess since this feature is odd, and has no simple semantic explanation as expansion into a body, making it a bit odder by having (what appears to the uninitiated as) an exception to the expected freezing by a body is no big deal. After all one cannot imagine a program being damaged by the *lack* of freezing, so if all implementations avoid the freeze, I don't see any real harm. I do see harm if we change implementations the other way, since this can indeed cause working programs to fail. **************************************************************** From: Robert A Duff Sent: Wednesday, April 05, 2000 8:06 AM Generic instantiations can cause bodies to appear in specs, even though bodies are syntactically illegal in specs. Strange, perhaps, but we've learned to live with it. ****************************************************************