Version 1.1 of ais/ai-00332.txt

Unformatted version of ais/ai-00332.txt version 1.1
Other versions for file ais/ai-00332.txt

!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)
Replace the paragraph:
When the expected type for a construct is required to be a single 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 type_conversion.
by:
When the expected type for a construct is required to be a single 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 qualified_expression identifies a single type (namely, the type specifed by the subtype_mark), 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 type_conversion.
!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<single> 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<qualified_expression> identifies a
single type (namely, the type specifed by the @fa<subtype_mark>), 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<type_conversion>.

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<operand> (the @fa<expression> or @fa<aggregate>) is
the type determined by the @fa<subtype_mark>. The operand shall have the type
determined by the @fa<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. 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<operand> (the @fa<expression> or @fa<aggregate>)
> is the type determined by the @fa<subtype_mark>. The operand shall have the
> type determined by the @fa<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. But maybe it is better??

Seems better to me.  Maybe the goofiness can be attenuated by starting
the second sentence with "Furthermore, ".

****************************************************************


Questions? Ask the ACAA Technical Agent