!standard 4.7 (03) 03-07-25 AI95-00320/01 !standard 8.6 (27) !class binding interpretation 03-07-25 !status work item 03-07-25 !status received 03-03-17 !qualifier Omission !priority Low !difficulty Medium !subject Resolution of qualified expressions !summary Access attributes, character literals, and other constructs requiring a single expected type can be used as the operand of a qualified expression. !question Which of the following allocators is legal? procedure test47 is type T1 is tagged null record; type T1_Acc is access T1; type T1_Class_Acc is access T1'Class; procedure Proc (X : in T1; Y : in T1'Class) is P1 : T1_Acc; P2 : T1_Class_Acc; begin P1 := new T1' (Y); -- IS THIS LEGAL? P2 := new T1'Class' (X); -- IS THIS LEGAL? end Proc; begin null; end test47; The language of 4.7(3) says the operand "shall resolve to" be of the type determined by the subtype mark, as opposed to most of the other name resolution rules that talk about what the expected type is. This seems to mean that the operand (or more strictly, an acceptable interpretation of the operand) has to be of the same type determined by the subtype mark. This would seem to mean that both are illegal, because Y resolves to T1'Class instead of T1, and X resolves to T1 instead of T1'Class. Is that the correct interpretation? (Yes.) Another question regarding qualified expressions: type T1 is record ... end record; type Acc_1 is access all record; type Acc_2 is access all record; X : aliased T1; procedure Some_Proc (Param : in Acc_1); procedure Some_Proc (Param : in Acc_2); Some_Proc (Acc_1' (X'Access)); -- OK (Yes.) Some_Proc (Acc_1' (null)); -- OK (Yes.) Are these qualified expression legal? (Yes.) One possible reading would say that it isn't, because 3.10.2(2) says that the type of X'Access is determined by the expected type, and the Name Resolution Rules for a qualified expression don't specify what the expected type of the operand is (again, unlike the Name Resolution Rules for many other Ada constructs). So if there's no expected type, 3.10.2(2) doesn't know what type X'Access should have. The same reading holds for 4.2(2). !recommendation (See Wording.) !wording Add an AARM note to 4.7(3): This means that the operand must have exactly the type of the subtype_mark. This is different than having an expected type (as for most other resolution rules), which allow classwide types to match specific types. Add the following to 8.6(27): In particular, when a single type is required, the operand of a qualified_expression identifies a single type (namely, the type specifed by the subtype_mark), and that type is the expected type of the operand. AARM Note: To be honest: A qualified expression's operand does not have an expected type, unless a single type is required. !discussion "shall resolve to" is defined in 8.6. It clearly applies here, so that a classwide operand cannot be used with a specific type qualified expression. However, the "expected type" of the operand is not defined. This matters only in cases where a single expected type is required (such as an Obj'Access attribute). We clearly want to allow 'Access attributes in a qualified expression (it may be the only way to insure that they resolve), and the expression clearly meets the tests for a single type. However, since it does not have an "expected type", we need to explicitly say that it is OK. It would be cleaner to define the expected type of the operand of a qualified expression for all cases, but that would allow classwide expressions to match specific type qualifications, which we do not want to allow. It might appear that we could put this text in 3.10.2(2), which is where the resolution of Obj'Access is defined. However, other constructs also use "expected type is a single blah type", such as null, character literals, and string literals. We don't want to be defining all of these places. An alternative would be to replace 4.7(3) by: The expected type of the operand (the expression or aggregate) is the type determined by the subtype_mark. The operand shall have the type determined by the subtype_mark, or a universal type that covers it. This is goofy, because we're giving the rule twice, with the second more restrictive that the first. The second rule must be a name resolution rule; if it was a legality rule ambiguities would be introduced, which would be contrary to the purpose of qualified expressions. !corrigendum 8.6(27) @drepl When the expected type for a construct is required to be a @i type in a given class, the type expected for the construct shall be determinable solely from the context in which the construct appears, excluding the construct itself, but using the requirement that it be in the given class; the type of the construct is then this single expected type. Furthermore, the context shall not be one that expects any type in some class that contains types of the given class; in particular, the construct shall not be the operand of a @fa. @dby When the expected type for a construct is required to be a @i type in a given class, the type expected for the construct shall be determinable solely from the context in which the construct appears, excluding the construct itself, but using the requirement that it be in the given class; the type of the construct is then this single expected type. In particular, when a single type is required, the operand of a @fa identifies a single type (namely, the type specifed by the @fa), and that type is the expected type of the operand. Furthermore, the context shall not be one that expects any type in some class that contains types of the given class; in particular, the construct shall not be the operand of a @fa. !ACATS test Existings ACATS tests test resolution. !appendix !topic Qualified expressions, meaning of "resolve to" !reference RM95 4.7(3), AARM95 4.8(4a), RM95 3.10.2(24) !from Adam Beneschan 03-17-03 !discussion Which of the following allocators is legal? procedure test47 is type T1 is tagged null record; type T1_Acc is access T1; type T1_Class_Acc is access T1'Class; procedure Proc (X : in T1; Y : in T1'Class) is P1 : T1_Acc; P2 : T1_Class_Acc; begin P1 := new T1' (Y); -- IS THIS LEGAL? P2 := new T1'Class' (X); -- IS THIS LEGAL? end Proc; begin null; end test47; I have been going back and forth on this question, and now I'm not sure what the answer is. The language of 4.7(3) says the operand "shall resolve to" be of the type determined by the subtype mark, as opposed to most of the other name resolution rules that talk about what the expected type is. This seems to mean that the operand (or more strictly, an acceptable interpretation of the operand) has to be of the same type determined by the subtype mark. This would seem to mean that both are illegal, because Y resolves to T1'Class instead of T1, and X resolves to T1 instead of T1'Class. Is that the correct interpretation? If not, why not? AARM 4.8(4a) says, Ramification: For example, ... new S'Class ... (with no initialization expression) is illegal, but ... new S'Class'(X) ... is legal, and takes its tag and constraints from the initial value X. (Note that the former case cannot have a constraint.) Although this paragraph doesn't say specifically what X is, the implication seems to be that X can be a value whose type is any type in S'Class, and that the allocator takes its tag from the initial value. In other words the implication is that something like the assignment to P2 in the above example should be legal, which contradicts the interpretation I gave above. Another question regarding qualified expressions: type T1 is record ... end record; type Acc_1 is access all record; type Acc_2 is access all record; X : aliased T1; procedure Some_Proc (Param : in Acc_1); procedure Some_Proc (Param : in Acc_2); Some_Proc (Acc_1' (X'Access)); Is this qualified expression legal? One possible reading would say that it isn't, because 3.10.2(24) says that the type of X'Access is determined by the expected type, and the Name Resolution Rules for a qualified expression don't specify what the expected type of the operand is (again, unlike the Name Resolution Rules for many other Ada constructs). So if there's no expected type, 3.10.2(24) doesn't know what type X'Access should have. Sorry if this all seems pedantic, but I'm genuinely confused here, and am wondering if some clarification in the RM (or AARM) is warranted. I appreciate any assistance anyone can give. **************************************************************** From: Randy Brukardt Sent: Monday, March 17, 2003 11:52 PM > ...The language of 4.7(3) says the operand > "shall resolve to" be of the type determined by the subtype mark, as > opposed to most of the other name resolution rules that talk about > what the expected type is. This seems to mean that the operand (or > more strictly, an acceptable interpretation of the operand) has to be > of the same type determined by the subtype mark. This would seem to > mean that both are illegal, because Y resolves to T1'Class instead of > T1, and X resolves to T1 instead of T1'Class. "Shall resolve to" is commonly used in the RM (I found 30 pages using it in the AARM - check the search page at http://www.adaic.com/standards/95aarm/html/AA-SRCH.html). I believe that 8.6(14) is intended to define what "shall resolve to" means, although that description seems weak to me - and the AARM notes are no help. However, I believe the intent is that it resolves exactly to the type (the normal rules about class-wide types don't apply here). Thus, your original examples are illegal. > Although this paragraph doesn't say specifically what X is, the > implication seems to be that X can be a value whose type is any type > in S'Class, and that the allocator takes its tag from the initial > value. In other words the implication is that something like the > assignment to P2 in the above example should be legal, which > contradicts the interpretation I gave above. No, X has to have type S'Class. But of course the actual type of the object X could be any type in S'Class. That's just normal class-wide programming. I don't see any implication of the type of X here. >... > Some_Proc (Acc_1' (X'Access)); > > Is this qualified expression legal? One possible reading would say > that it isn't, because 3.10.2(24) says that the type of X'Access is > determined by the expected type, and the Name Resolution Rules for a > qualified expression don't specify what the expected type of the > operand is (again, unlike the Name Resolution Rules for many other Ada > constructs). So if there's no expected type, 3.10.2(24) doesn't know > what type X'Access should have. That does appear to be a hole, although you're looking at the wrong paragraph: it's 3.10.2(2) that defines this. (Note that 3.10.2(2) is substantially changed by AI-235, but still has the expected type wording). So it does appear that some connection between expected type and "shall resolve to" is necessary. But perhaps someone else can explain the (invisible) connection. > Sorry if this all seems pedantic, but I'm genuinely confused here, and > am wondering if some clarification in the RM (or AARM) is warranted. > I appreciate any assistance anyone can give. Well, we do need to be pedantic from time-to-time. It's not clear to me that the wording adquately embodies the intent. It is clear that 4.7(3) couldn't use "expected type", because that would allow class-wide matching, and that is not desired for qualified expressions. But I don't see any way to connect "shall resolve to" (which doesn't seem to be talking about types) to "expected types". I hope that Bob or Tuck enlightens us as to how the wording actually matches the intent. :-) **************************************************************** From: Tucker Taft Sent: Tuesday, March 18, 2003 10:50 AM I think we were a bit fast and loose with the phrase "single expected type." A qualified expression definitely creates an "expectation" for a "single" type, but doesn't use the term "expected type" itself (for good reason, as Randy points out, that would kick in the class-wide matching rules). So 8.6(27) should probably be clarified to explicitly included a qualified expression as a construct that satisfies the requirement for a "single expected type." ... > I hope that Bob or Tuck enlightens us as to how the wording actually matches > the intent. :-) I don't know if I helped, but I gave it a try... **************************************************************** From: Christoph Grein Sent: Thursday, March 20, 2003 5:25 AM > Thus, your original examples are illegal. Just for information - hope someone from ACT listens, Gnat 3.16a: procedure test47 is type T1 is tagged null record; type T1_Acc is access T1; type T1_Class_Acc is access T1'Class; procedure Proc (X : in T1; Y : in T1'Class) is P1 : T1_Acc; P2 : T1_Class_Acc; begin P1 := new T1' (Y); -- IS THIS LEGAL? Gnat says yes. not OK P2 := new T1'Class' (X); -- IS THIS LEGAL? Gnat says no. OK -- I think the effect of the above illegal statements -- can be achieved like so: P1 := new T1'(t1 (Y)); P2 := new T1'Class'(t1'class (X)); end Proc; **************************************************************** From: Tucker Taft Sent: Thursday, March 20, 2003 10:13 AM For what it's worth, I have attached the listing produced by the AdaMagic front end for this example. It rejects both of the illegal allocators. --- Source file: qualified.ada Thu Mar 20 11:11:07 2003 1 procedure qualified is 2 type T1 is tagged null record; 3 4 type T1_Acc is access T1; 5 type T1_Class_Acc is access T1'Class; 6 7 procedure Proc (X : in T1; Y : in T1'Class) is 8 P1 : T1_Acc; 9 P2 : T1_Class_Acc; 10 begin 11 P1 := new T1' (Y); -- IS THIS LEGAL? Gnat says yes. not OK * *****Error: LRM:8.6(28) Expression has no possible interpretation as an ***** expression of the type T1, Continuing 12 P2 := new T1'Class' (X); -- IS THIS LEGAL? Gnat says no. OK * *****Error: LRM:8.6(28) Expression has no possible interpretation as an ***** expression of the type T1'Class, Continuing 13 -- I think the effect of the above illegal statements 14 -- can be achieved like so: 15 P1 := new T1'(t1 (Y)); 16 P2 := new T1'Class'(t1'class (X)); 17 end Proc; 18 19 begin 20 null; 21 end; **************************************************************** From: Randy Brukardt Sent: Friday, July 25, 2003 5:42 PM Janus/Ada also rejects both allocators. **************************************************************** From: Randy Brukardt Sent: Friday, July 25, 2003 7:13 PM I've been working on the big backlog of boring AIs. I wrote up this AI, but am not very happy with the wording. Perhaps someone has a better suggestion. Anyway, here is the relevant question from the AI. (There is another question, which is why I'm not appending the AI itself.) --- type T1 is record ... end record; type Acc_1 is access all record; type Acc_2 is access all record; X : aliased T1; procedure Some_Proc (Param : in Acc_1); procedure Some_Proc (Param : in Acc_2); Some_Proc (Acc_1' (X'Access)); -- OK (Yes.) Some_Proc (Acc_1' (null)); -- OK (Yes.) Are these qualified expression legal? (Yes.) One possible reading would say that it isn't, because 3.10.2(2) says that the type of X'Access is determined by the expected type, and the Name Resolution Rules for a qualified expression don't specify what the expected type of the operand is (again, unlike the Name Resolution Rules for many other Ada constructs). So if there's no expected type, 3.10.2(2) doesn't know what type X'Access should have. The same reading holds for 4.2(2). --- Clearly, we want these cases to work, so the only question is what the wording should be to fix the whole. Tucker suggested changing 8.6(27), and since I don't see any other uses of "expected type" for the results of expressions, I did that. Replace 8.6(27) by: When the expected type for a construct is required to be a @i type in a given class, the type expected for the construct shall be determinable solely from the context in which the construct appears, excluding the construct itself, but using the requirement that it be in the given class; the type of the construct is then this single expected type. In particular, when a single type is required, the operand of a @fa identifies a single type (namely, the type specifed by the @fa), and that type is the expected type of the operand. Furthermore, the context shall not be one that expects any type in some class that contains types of the given class; in particular, the construct shall not be the operand of a @fa. The sentence starting with "In particular" is new. I'm not very happy with this wording. We're defining expected type for the operands of qualified expressions only when a single type is needed. Otherwise, there is no expected type. This seems necessary because in other cases the rules of 8.6(22-25) would be triggered, and we definitely don't want them used for the operands of qualified expressions. An alternative would be to replace 4.7(3) by: The expected type of the @i (the @fa or @fa) is the type determined by the @fa. The operand shall have the type determined by the @fa, or a universal type that covers it. This is goofy, because we're giving the rule twice, with the second more restrictive that the first. But maybe it is better?? (Note that the second rule cannot be a legality rule without introducing ambiguity where there currently is none.) **************************************************************** From: Robert A Duff Sent: Friday, July 25, 2003 7:43 PM > The expected type of the @i (the @fa or @fa) > is the type determined by the @fa. The operand shall have the > type determined by the @fa, or a universal type that covers > it. > > This is goofy, because we're giving the rule twice, with the second more > restrictive that the first. But maybe it is better?? Seems better to me. Maybe the goofiness can be attenuated by starting the second sentence with "Furthermore, ". ****************************************************************