!standard 7.6(17.1/3) 11-01-20 AI05-0232-1/01 !class confirmation 11-01-20 !status work item 10-10-25 !status received 10-09-24 !priority Low !difficulty Easy !subject Hole in AI05-0067-1 !summary Whether a call is required to be built-in-place is a dynamic property of the object. !question Is the following call built-in-place? type Interface_Type is limited interface; Obj : Interface_Type'Class := Some_Function(...); where Some_Function is declared as returning Interface_Type'Class. Interface_Type'Class is not immutably limited, since a type derived from Interface_Type could be limited or nonlimited (AARM 7.5(8.c)). This would seem to mean that it's unspecified whether this function call is built in place, since the rule in 7.6(17.2) refers to the (full) type of the object, not to the type determined by the tag of the function result. But this doesn't seem desirable, since the function result *could* be of a limited type, and in that case we still want to have the result built in place, with no copying. Is a fix needed? (No.) !response The existing wording is correct. RM 7.6 states: When a function call or aggregate is used to initialize an object, the result of the function call or aggregate is an anonymous object, which is assigned into the newly-created object. For such an assignment, the anonymous object might be built in place. Under certain circumstances, the anonymous object is required to be built in place, in which case the assignment does not involve any copying. In particular: If the full type of any part of the object is immutably limited, the anonymous object is built in place. ... One part of any object is the object itself, so this rule implies that build-in-place is required if the full type of the object is immutably limited. But because this wording is under "Dynamic Semantics", 3.1(7/3) does not apply and thus views are not involved here. For a given part, this wording refers to the specific nonabstract type of the part. Also note that parts other than the object itself cannot be class-wide (as indefinite components are not allowed); thus there always is a specific type. In the case that the object itself has a class-wide type (as opposed to a specific tagged type), this wording refers to the type identified by the tag of the part. [One could imagine that we ought to have a "To Be Honest" note to cover this unlikely case - although if we do that, we need to classify this as a ramification - Randy.] This is what distinguishes this situation from the related question addressed in AI05-0099-1, where explicit wording changes such as "If the full type of the object is a tagged type, and the tag of the object identifies a controlled type.", were needed. [Not quite sure I buy this; that wording originally seemed to imply a compile-time determination of the type -- it said "is of", not just "is" -- while this wording is clearly runtime. Even so, this seems to be a horribly weak argument. We decided in AI05-0099-1 that there is no implicit "dynamic type" for an object, so to assume one here is uncomfortable. It would be better to bite the bullet and add explicit words like the above to the 7.6(17.1/3) rule. - Randy.] In the case of a function returning Some_Limited_Interface_Type'Class, build-in-place is required if and only if the specific nonabstract type of the function result is immutably limited. This means that for two different elaborations of the object declaration given in the question, one call to Some_Function might require build-in-place while the other might not. !ACATS Test !appendix !topic Possible hole in AI05-0067? !reference 7.6(17.1/3-17.4/3) !from Adam Beneschan 10-09-24 !discussion I've just now found a reason to look over the new build-in-place rules, and I've run into something that may be an important omission. The new rules say that, for a function call used to initialize an object, the function call must be built in place if the object's type is immutably limited, but it's unspecified whether it's built in place in other cases. What happens in this case? type Interface_Type is limited interface; Obj : Interface_Type'Class := Some_Function(...); where Some_Function is declared as returning Interface_Type'Class. Interface_Type'Class is not immutably limited, since a type derived from Interface_Type could be limited or nonlimited (AARM 7.5(8.c)). This would seem to mean that it's unspecified whether this function call is built in place, since the rule in 7.6(17.2) refers to the (full) type of the object, not to the type determined by the tag of the function result. But this doesn't seem desirable, since the function result *could* be of a limited type, and I'd think that in this case we still want to have the result built in place, with no copying. Should 7.6(17.1-17.4) be modified to require build in place when an object type is the 'Class of a limited interface type? I don't think this would be harmful in cases where the function result is actually a nonlimited type (see the last sentence of AARM 7.6(17.o)), but maybe there are cases where it would be a problem. (An alternative would be to require implementations to build the result in place if the function result's tag identifies a limited type, and let them choose if it identifies a nonlimited type. But from my point of view, in our implementation, generating code to decide this at runtime isn't feasible.) **************************************************************** Following is the edited end of a private conversation about this AI: Randy Brukardt: Thanks. I turned this into a complete AI. But you've made me dubious of the conclusion that we came to. I think we need *at least* an AARM To-Be-Honest note (in which case this is a Ramification) or a bit of full-blown wording (in which case it is a BI), because the leap that you use to assume we use the tag doesn't make much sense. Steve Baird: Oh dear, we seem to have exchanged positions. I thought the conclusion made sense. The point is that when we are talking about the type of an arbitrary part of an object in a dynamic semantics check, and if that part happens to be tagged, we (as you explained to me) couldn't very well be talking about anything other than specific, nonabstract type associated with the part's tag. This is unchanged if the part we happen to be considering (as part of a rule that applies to all parts of an object) is the object itself. The object's (nominal) type might be abstract and/or classwide, but that's irrelevant. Randy Brukardt: The conclusion makes sense. But it doesn't match the way the standard is written. And I was explaining to you that you always look at the type of the parts of the actual returned object, not of the nominal type of the function. I had incorrectly convinced myself that that never required inspection of the tag (see below). I definitely agree that we don't care about the nominal subtype. But go back and read AI05-0099-1 again. It concludes: (1) The standard does not define a "dynamic type". (2) The standard always specifies when the tag needs to be consulted to determine a property. Ergo, we needed to make a wording change for that AI. The same applies here. Yesterday, I thought that you always knew that type somewhere, because components cannot have class-wide types, and the types of parts are only (logically) consulted when the return statement is executed. For an abstract class-wide type as in the example, you have to be returning an object that is of some other specific type (so you know the type there). No tag reading needed in either case. But I forgot that you could also return some sort of class-wide object (either a stand-alone object or another function call); if that object has no inherently limited parts, then there is nowhere else to look; while that is unusual it is possible, and in those cases you'd probably need to consult the tag. If you need to consult the tag, we need wording (or at least a To Be Honest note). The problem that the ARG has had is that we were focusing on Adam's question. His question is bogus, because this is a dynamic property that doesn't necessarily get determined until the instant that the return statement starts returning the object. It is inspection of the returned object, and not anything about the properties of the function, that determines whether build-in-place is required. So there is no problem at the call site (which is what he asked): the function (and its call) has to be able to return a object that is build-in-place, but it only has to do that if the actual object requires that. But there still is a problem *inside* the function with the inspection of the returned object. The model is correct, but to properly use that model we need some wording -- because there is no such thing as a dynamic type. And we all agree that we're not (only) looking at the nominal type of the parts of that object (the subtype is irrelevant of course). I think just a To Be Honest note would be sufficient, because "requires build-in-place" is not a property that you can query -- thus being unambiguous about the runtime value is not that critical. All an implementation has to do is ensure that no case that "requires build-in-place" is copied; it is perfectly OK to build-in-place cases that do not need to be handled that way. But I think we do need to mention in the standard that you might have to query the tag to determine this property -- or "assume-the-worse" about class-wide objects. That means this is a ramification and not a confirmation, and thus it has to be rewritten again. ****************************************************************