Version 1.10 of ais/ai-00235.txt
!standard 03.10.02 (02) 01-09-11 AI95-00235/05
!class binding interpretation 00-05-31
!status ARG Approved 8-0-2 00-11-19
!status work item 00-05-09
!status received 00-05-09
!qualifier Clarification
!priority High
!difficulty Medium
!subject Resolving 'Access
!summary
The prefix type of 'Access (and 'Unchecked_Access) can be used to resolve the
expected access type.
!question
3.10.2(2) requires that the expected type of 'Access (and 'Unchecked_Access)
is "a single access type". This means that some expressions which might be
resolved are illegal:
type Int_Ptr is access all Integer;
type Float_Ptr is access all Float;
function Zap (Val : Int_Ptr) return Float;
function Zap (Val : Float_Ptr) return Float;
...
Value : aliased Integer := 10;
Result1 : Float := Zap (Value'access); --
Result2 : Float := Zap (Int_Ptr'(Value'access)); --
Existing Ada 95 compilers vary widely as to whether or not they allow
expressions like Result1's initializer.
Should we allow additional flexibility here? (Yes.)
!recommendation
(See summary.)
!wording
Replace 3.10.2(2) with:
For an attribute_reference with attribute_designator Access (or
Unchecked_Access -- see 13.10), the expected type shall be a single access
type A such that:
ú A is an access-to-object type with designated type D and the type of
the prefix is D'Class or is covered by D, or
ú A is an access-to-subprogram type whose designated profile is type
conformant with that of the prefix.
[The prefix of such an attribute_reference is never interpreted as an
implicit_dereference or parameterless function_call (see 4.1.4).] The
designated type or profile of the expected type of the attribute_reference
is the expected type or profile for the prefix.
!discussion
A compiler survey of the most popular compilers shows that two compilers
implement the existing RM wording reasonably closely, while four other
compilers allow varying degrees of overloading resolution in this case.
The easiest course of action would be simply to confirm the RM, and
require the implementors to conform. However, it is clear that real Ada
users trip over this rule periodically. It was a significant Ada user that
contacted the ACAA with the fact that compilers differ in their implementation
of this rule, which eventually led to the creation of this AI.
The user problem is most severe when an anonymous access type is involved:
function Do_It (Obj : access Integer) return Boolean;
function Do_It (Obj : access Float) return Boolean;
if Do_It (Value'access) then ... --
Code like this is common in interfacing packages, where an anonymous access
type is used to implement *p parameters of C in functions (because in out
parameters are not allowed there).
To work around the problem caused by the original RM rule, a named access type
has to be introduced, so that it can be used in a qualified expression:
if Do_It (Int_Ptr'(Value'Access)) then ... -- OK.
But this is not quite equivalent, because the accessibility rules for anonymous
access types are different from named access types. (The use of the qualified
expression changes the accessibility check for the Access attribute from the
anonymous type to the named type.) Thus, the user will have to declare
an access type in the scope of each call, or will have to change to using
'Unchecked_Access.
Since some compilers allow the resolution of expressions like that in the
question and in the example above, it is likely that real-world systems depend
on being able to resolve these expressions. If the rule 3.10.2(2) was confirmed
and compilers changed to conform, this existing user code would break for no
good reason.
Therefore, we adopt a liberalized rule. The new rule has to be careful to
include the "single access type" wording, in order that 'Access not be
allowed in type conversions or other contexts where a specific type is not
identified.
!corrigendum 3.10.02(2)
Replace the paragraph:
For an attribute_reference with attribute_designator Access (or
Unchecked_Access -- see 13.10), the expected type shall be
a single access type; the prefix of such an attribute_reference
is never interpreted as an implicit_dereference. If the expected
type is an access-to-subprogram type, then the expected profile
of the prefix is the designated profile of the access type.
by:
For an attribute_reference with attribute_designator Access (or
Unchecked_Access -- see 13.10), the expected type shall be
a single access type A such that:
- A is an access-to-object type with designated type D and the type of
the prefix is D'Class or is covered by D, or
- A is an access-to-subprogram type whose designated profile is type
conformant with that of the prefix.
The prefix of such an attribute_reference is never interpreted as an
implicit_dereference or parameterless function_call (see 4.1.4).
The designated type or profile of the expected type of the
attribute_reference is the expected type or profile for the prefix.
!ACATS test
ACATS test B3A2016.A, introduced in December 1999, tests this issue.
A C-test should be created out of the example test circulated in June 2000,
and the commented out cases in B3A2016.A replaced.
!appendix
From: Randy Brukardt
Sent: Tuesday, May 9, 2000 5:20 PM
At the recent ARA meeting, Robert Dewar expressed some concern about a new ACATS
test which is intended to check 3.10.2(2) for objects. (There was no test for
this rule in the past.) This rule says that the prefix of an access attribute is
not used to resolve the expression which contains it. I created the new ACATS
test from a test case that was submitted by a large Ada user. They had run into
problems with different compilers supporting different resolution algorithms. My
experiments with the test program shows that compilers implement the rule
differently, ranging from (almost) strict RM to using the maximum information.
Robert was concerned that forcing compilers to follow the RM rules could break
existing user code that depends on this "feature"; he thought it was especially
likely to occur in interfacing code. (Hopefully, Robert will expand on this
concern.)
The basic test case is the following:
type Int_Ptr is access all Integer;
type Char_Ptr is access all Character;
type Float_Ptr is access all Float;
function Zap (Val : Int_Ptr) return Float;
function Zap (Val : Float_Ptr) return Float;
...
Value : aliased Integer := 10;
Result1 : Float := Zap (Value'access); -- ERROR: Ambiguous.
Result2 : Float := Zap (Int_Ptr(Value'access)); -- ERROR: Type conversion (8.6(27)).
Result3 : Float := Zap (Int_Ptr'(Value'access)); -- OK.
While the only legitimate interpretation of Value'access is as an Int_Ptr,
3.10.2(2) makes it clear that any access type matches it; thus we cannot resolve
between the two cases of Zap.
A few Ada compilers do get this right.
---
More recently, I noticed that the rule says "single access type", not "single
GENERAL access type", so I added the following test case (not yet issued):
type Int_Ptr is access all Integer;
type Pool_Int_Ptr is access Integer;
function Zip (Val : Int_Ptr) return Float;
function Zip (Val : Pool_Int_Ptr) return Float;
...
Value : aliased Integer := 10;
Result4 : Float := Zip (Value'access); -- ERROR: Ambiguous.
Result5 : Float := Zip (Int_Ptr(Value'access)); -- ERROR: Type conversion (8.6(27)).
Result6 : Float := Zip (Int_Ptr'(Value'access)); -- OK.
Again, the only legitimate interpretation of Value'access is as an Int_Ptr
('access never returns a pool-specific access type), but again we can't use
this. 3.10.2(2) makes it clear that any access type matches it for resolution
purposes; thus we cannot resolve between the two cases of Zip.
No Ada compiler I tried gets this example right.
---
We have three choices (with the third choice open-ended):
1) We can simply file this as No Action, and direct the ACAA not to test it. I
don't think this serves anyone well: compilers will continue to differ, vendors
will get bug reports about their compilers being incompatible with the standard,
and users will encounter problems porting code. It is clear this issue is of
more than academic interest, as at least one real Ada user has encountered it in
practice. Moreover, ACT is concerned about the effects of correcting their
compiler; this implies to me that they also feel that it is a real issue.
Therefore, I reject this choice.
2) We can confirm the standard. The ACAA will keep the test in the ACATS suite,
and it will become effective July 1st. This means that several compilers will
need to be changed, and some users may be impacted. This is the default action:
if we do nothing at all, this is what will happen.
3) We can change the standard. I am somewhat uncomfortable about this option, as
there is no technical problem with the language. We have done that at least once
in the past, but in that case there was an existing ACATS test to which all
compilers conformed: thus the language change had no impact on compilers or
users. Indeed it brought the language into compliance with practice. In this
case, we have compilers which DO follow the RM. A language change would impact
those vendors (although not their users, as more expressions would be made
legal).
I'm not sure what the rule ought to be changed to if it is changed. I don't
think that simply eliminating the rule works very well. Quite ugly expressions
can be constructed that may be hard to resolve, especially if compilers take any
advantage of the "single access type" rule. There also may be technical problems
allowing 'access as the operand of a type conversion (what is the type if there
is more than one possible general access type that matches the prefix? Do we
need to "search" for all possible access types before deciding this??).
One ugly case, with the declarations of the first example above:
function Zop return Int_Ptr;
function Zop return Char_Ptr;
...
Value : aliased Integer := 10;
Resultx : Float := Zap (Zop.all'access);
This expression can be resolved, as there is only one interpretation where all
of the types match, but do we really want to go through the work to allow it??
OTOH, changing 3.10.2(2) to say "single general access type" would make the rule
match compilers more closely, and I think it is harmless.
Whatever is done with the rule, I believe that the ACATS ought to test it, to
insure that compilers all conform to the standard.
Randy Brukardt
ACAA Technical Agent.
****************************************************************
From: Robert Dewar
Sent: Tuesday, May 09, 2000 6:07 PM
1) It is better to use an example with access parameters, because
in this case there *is* no easy fix, because there is no type name
to use in a qualification, so a junk type access type has to be introduced
which is quite unpleasant.
2) It is not right to say that we have compilers which "DO follow
the RM", as you made it clear that "no Ada compiler I tried gets this
right" for one of the examples. This means that if you choose option
2, then *all* compilers will need to be changed.
3) The only reason for not using the context to help resolve here
seems to be the arbitrary Ada 83 rule that attributes must be resolved
without using context (more precisely that the prefix of the attribute
must be resolved without using context). But the 'Access operator was
not in Ada 83, so it is not clear that makes sense.
4) We already made an exception to this Ada 83 principle for
the case of access to subprogram, so why not access to object as well.
5) The idiom of using x'access and access parameters in calls, especially
to interfaced routines in a foreign language is a common one. It is the
cleanest workaround to the rule that you cannot have in out parameters in
functions, as required for interfacing to many C functions for example.
6) Do we really do users a favor by fixing this? Yes, it is a problem
for portability, but why value portability over consistency to such an extent
that you will force lots of users to change their programs now instead of
later. Portability is after all a user concern, so if we are going to argue
portability, we also have to be concerned with the impact on users. In this
case the impact would be significant.
7) If we have a choice between changing the test suite so that users
can do MORE than they could before, and changing it so that they can do
LESS than they could before, how is this a benefit. It seems clear that
it is far more useful to users to take Randy's option three.
8) I object to the statement that the default is that the test goes in. No
test should go into the suite without specific ARG discussion that includes
issues of impact on users, and also value of the test. Please let's not get
into a situation where changes to the tests once again tend to give the suite
a bad name. The suite is there to help users, not to hurt them.
9) I sort of understand the idea that if several compilers get something
"right" and several get it "wrong" that there is a tendency to think it is
fairer to change the ones that are "wrong". However, in this case (a) there
is no compiler that really gets it right and (b) this in any case is a
principle designed with compiler writers benefits in mind rather than
user benefits. Note that we have quite a few times changed the clear
language in the RM in a way that makes correct compilers change under
the influence of incorrect compilers doing things wrong, if on reflection
we feel that wrong is right. An excellent example of this is the non-
static status of System.Bit_Order. GNAT carefully made this non-static
and got lots of user complaints. Green Hills (and I assume other compilers
using the same front end made it static which was clearly wrong. GNAT made
the change because it was clearly in the best interests of users.
10) I think that changing this is in accordance with the principle of
least surprise. The overloading rule after all should be that if there
is only one interpretation and it is not likely to cause confusion, then
that's the one that should be used. We compromise this for the benefit
of implementation simplicity sometimes, but I don't see that this
principle applies in this case.
11) The original Ada 83 rule that prefixes have to be resolved without
context is not particularly worrisome, as there are very few cases where
it would be annoying. But 'Access is really a completely different kind
of beast. It might well be an operator in the language, in which case of
course this would work, but for various reasons it ended up as an attribute
but I see no reason why this choice should cause ambiguity problems.
12) I suspect that the change required in compilers is small either way.
Certainly in GNAT it is trivial to make the change (we almost did it, and
then I complained that it would be a real pain to users, so we hesitated
for now). It was an easy-to-find two line change. Let's not use the
argument of compilers being difficult to change, until we find that this
is really true. Remember that *all* compilers will have to change if
we choose Randy's option number 2.
13) I really dislike rules where the resolution depends on whether a type
is a general or pool-specific access type, that seems really junky and
quite unintuitive.
For all these reasons, my order of preference is 3/1/2 in Randy's choices.
I realize that a little work is needed for choice 3, and so let's for now
look at choice 3, and formulate the EXACT replacement rule, before we decide
whether to adopt it or not.
****************************************************************
From: Pascal Leroy
Sent: Wednesday, May 10, 2000 4:09 AM
> Robert was concerned that forcing compilers to follow the RM rules could
> break existing user code that depends on this "feature"; he thought it was
> especially likely to occur in interfacing code. (Hopefully, Robert will
> expand on this concern.)
This is a rather weak argument. Compiler writers have been fixing bugs for
about 15 years, and we all know that occasionally fixing a bug will cause grief
and sorrow because some users will discover that their code depended on the bug.
Such situations are normally dealt with by a frank and open discussion between
the user and the vendor. The outcome may be anything from "you've got to change
your code" to "we are going to provide a bug-compatibility option just for you".
Bug-compatibility is certainly not a good reason for changing the language. The
only valid question is: would the language be more useful with the proposed
change? I am tempted to say yes, but to make a definite answer I would need to
see a precise proposal, not just some hand-waving.
> 3) We can change the standard. I am somewhat uncomfortable about this
> option, as there is no technical problem with the language. We have done
> that at least once in the past, but in that case there was an existing ACATS
> test to which all compilers conformed: thus the language change had no
> impact on compilers or users. Indeed it brought the language into compliance
> with practice. In this case, we have compilers which DO follow the RM. A
> language change would impact those vendors (although not their users, as
> more expressions would be made legal).
Note that in the case(s) where we changed the language, the change was rather
obvious; although I'm sure it took time and effort to come up with the correct
wording, the intent at least was pretty clear. In this case on the other hand,
it is very much unclear what the language should say (ie, how much information
do we want to use to lift ambiguities?).
> OTOH, changing 3.10.2(2) to say "single general access type" would make the
> rule match compilers more closely, and I think it is harmless.
No, it doesn't work. 3.10.2(2) applies to any occurrence of 'Access, including
those cases where the prefix is a subprogram. The phrases "single access type"
covers access-to-subprogram as well as access-to-object types. You could come
up with a similar ambiguity if one access type was an access-to-object and the
other an access-to-subprogram (and incidentally our compiler catches the
ambiguity in this case).
****************************************************************
From: Randy Brukardt
Sent: Wednesday, May 10, 2000 12:09 PM
Pascal said:
> Note that in the case(s) where we changed the language, the change was rather
> obvious; although I'm sure it took time and effort to come up with the correct
> wording, the intent at least was pretty clear. In this case on the other hand,
> it is very much unclear what the language should say (ie, how much information
> do we want to use to lift ambiguities?).
I agree; I tried to say this in my original post, but Pascal says it better.
Anyway, I think that someone who wants to change the language (Robert?) should
take the lead in providing a proposal for revising 3.10.2(2). I haven't been
able to come up with anything simple that provides the right answer and doesn't
run into problems. So while I'm sympathetic to the idea, I don't see how to
realize it.
> No, it doesn't work. 3.10.2(2) applies to any occurrence of
> 'Access, including those cases where the prefix is a
> subprogram. The phrases "single access type" covers
> access-to-subprogram as well as access-to-object types. You
> could come up with a similar ambiguity if one access type was
> an access-to-object and the other an access-to-subprogram
> (and incidentally our compiler catches the ambiguity in this case).
You are right of course. The existing ACATS test includes this case; I didn't
include it in my original message because it isn't particularly interesting.
****************************************************************
From: Tucker Taft
Sent: Wednesday, May 10, 2000 11:33 AM
Robert Dewar wrote:
> ...
> 3) The only reason for not using the context to help resolve here
> seems to be the arbitrary Ada 83 rule that attributes must be resolved
> without using context (more precisely that the prefix of the attribute
> must be resolved without using context). But the 'Access operator was
> not in Ada 83, so it is not clear that makes sense.
This is not quite right. We are *not* talking about problems resolving
the prefix, which in Ada 83 and Ada 95, must generally be unambiguous
using no context (the only exception being 'access for access-to-subp).
We are talking about resolving the surrounding function call.
> 4) We already made an exception to this Ada 83 principle for
> the case of access to subprogram, so why not access to object as well.
Again, the exception for access-to-subp refers to resolving the prefix.
In this case, the problem is resolving the enclosing function call.
If you look at the wording, there is a chicken-and-egg problem if
we allow the type of the prefix to help resolve the enclosing
function call, because we are currently using the enclosing function
call to resolve the prefix in the case of access-to-subp. The rule
for resolving the access-to-subp prefix presumes there is only
one access type coming "down" from outside.
Of course, there are already chicken-and-egg cases during overloading,
but the wording for 'access will require significant work to make
sure that the access-to-subp case still works OK.
>
> 5) The idiom of using x'access and access parameters in calls, especially
> to interfaced routines in a foreign language is a common one. It is the
> cleanest workaround to the rule that you cannot have in out parameters in
> functions, as required for interfacing to many C functions for example.
Since C doesn't support overloading, I wonder whether interfacing
to C is a great example in general.
>
> 6) Do we really do users a favor by fixing this? Yes, it is a problem
> for portability, but why value portability over consistency to such an extent
> that you will force lots of users to change their programs now instead of
> later. Portability is after all a user concern, so if we are going to argue
> portability, we also have to be concerned with the impact on users. In this
> case the impact would be significant.
This really means that you can't in fact overload functions where
the only difference is which designated types their access parameters
have.
> ...
> 11) The original Ada 83 rule that prefixes have to be resolved without
> context is not particularly worrisome, as there are very few cases where
> it would be annoying. But 'Access is really a completely different kind
> of beast. It might well be an operator in the language, in which case of
> course this would work, but for various reasons it ended up as an attribute
> but I see no reason why this choice should cause ambiguity problems.
As mentioned above, this has little to do with the resolution
of the prefix.
> ...
> 13) I really dislike rules where the resolution depends on whether a type
> is a general or pool-specific access type, that seems really junky and
> quite unintuitive.
>
> For all these reasons, my order of preference is 3/1/2 in Randy's choices.
> I realize that a little work is needed for choice 3, and so let's for now
> look at choice 3, and formulate the EXACT replacement rule, before we decide
> whether to adopt it or not.
I am sympathetic with this, but as indicated above, it is
not just following in the footsteps of the access-to-subp wording,
because that is focused on an overload prefix, where here we
are focused on an overloaded enclosing function call.
In fact, the access-to-subp wording actually causes more
trouble for dealing with an overloaded enclosing call.
Perhaps something like this would work for 3.10.2(2):
Name resolution rules:
For an attribute_reference with attribute_designator Access (or
Unchecked_Access -- see 13.10), the expected type shall be
a single access type whose designated type covers the type of
the prefix, or whose designated profile is type conformant
with that of the prefix.
This is fairly close to the wording for allocators [4.8(3)]. It is a bit
of an unorthodox use of the "shall be a single blah type" but
I think it is pretty clear how to implement this: Once you apply
the filtering based on designated type/profile matching, there
can't be any more ambiguity to be resolved by context.
****************************************************************
From: Robert A Duff
Sent: Wednesday, May 10, 2000 3:39 PM
> 11) The original Ada 83 rule that prefixes have to be resolved without
> context is not particularly worrisome, as there are very few cases where
> it would be annoying. But 'Access is really a completely different kind
> of beast. It might well be an operator in the language, in which case of
> course this would work, but for various reasons it ended up as an attribute
> but I see no reason why this choice should cause ambiguity problems.
It's not really true that 'Access could just as well be an operator,
because there are no operators that take subprograms as parameters.
Subprograms are not values, and do not have types -- they have profiles
instead.
****************************************************************
From: Robert A Duff
Sent: Wednesday, May 10, 2000 3:37 PM
To: ada-comment@ada-auth.org
> Perhaps something like this would work for 3.10.2(2):
>
> Name resolution rules:
>
> For an attribute_reference with attribute_designator Access (or
> Unchecked_Access -- see 13.10), the expected type shall be
> a single access type whose designated type covers the type of
> the prefix, or whose designated profile is type conformant
> with that of the prefix.
Thank you, Tucker. I tried to come up with wording today, and failed.
The above sounds exactly right, if we want to make this language
change. I suppose I could go along with this language change; I'm open
to either choice at this point.
I do think this issue is one where we need to have the exact RM wording
to argue intelligently about it.
I think the difference between pool-specific and general access types
should *not* be used to resolve these things, and the above wording
achieves that. Randy, is it really true that some compilers use the
pool-specific/general distinction to resolve these cases? Which ones?
****************************************************************
From: Randy Brukardt
Sent: Wednesday, May 10, 2000 4:10 PM
> > Perhaps something like this would work for 3.10.2(2):
> >
> > Name resolution rules:
> >
> > For an attribute_reference with attribute_designator Access (or
> > Unchecked_Access -- see 13.10), the expected type shall be
> > a single access type whose designated type covers the type of
> > the prefix, or whose designated profile is type conformant
> > with that of the prefix.
>
> Thank you, Tucker. I tried to come up with wording today, and failed.
> The above sounds exactly right, if we want to make this language
> change. I suppose I could go along with this language change; I'm open
> to either choice at this point.
On first glance, this looks pretty good. It clearly solves most of the
problems by leaving the "single access type" wording, which we need to avoid
using 'Access in type conversions.
One question, though, how does this work if the prefix is overloaded? That
is, given the third example in my original message, is it legal or illegal
(and why?)
> I do think this issue is one where we need to have the exact RM wording
> to argue intelligently about it.
Now that is a first for Bob: admitting that extra RM wording is necessary.
:-) :-)
> I think the difference between pool-specific and general access types
> should *not* be used to resolve these things, and the above wording
> achieves that. Randy, is it really true that some compilers use the
> pool-specific/general distinction to resolve these cases? Which ones?
Yes, of course. (You don't think I make these things up, I hope?) All but
one of the compilers I tried failed to detect the error in the second
example in my original posting. And I thought you told me that your compiler
failed that test as well.
Specifically:
Example 1 Example 2
GNAT 3.13a: No error No error
Apex 3.0.2b: Error No error
Janus/Ada 3.1.2: No error Error
Of these three, only Janus/Ada matches Tucker's proposed wording. (And given
it's market share, we probably can ignore it.)
The reason some ACATS test is desperately needed here is exactly that the
compilers all differ in what they allow and reject. If we change the
language, then I would change the test(s) accordingly (and issuing them
after the AI is approved by WG9) -- but I think it is a crime to let
compilers vary all over the map here.
****************************************************************
From: Gary Dismukes
Sent: Wednesday, May 10, 2000 5:40 PM
> One question, though, how does this work if the prefix is overloaded? That
> is, given the third example in my original message, is it legal or illegal
> (and why?)
It looks to me like the proposed rule doesn't work for your third
example (Zop.all'access). The phrase "covers the type of the prefix"
implies that there is a single type for the prefix, but that doesn't
address the overloaded case.
I agree with you that it's not worth trying to make that case legal,
but the rule needs to be fixed to address it. Maybe an extra rule
is needed to say that the prefix shall only have a single interpretation,
though that seems a bit ugly.
****************************************************************
From: Robert Dewar
Sent: Wednesday, May 10, 2000 7:55 PM
Thanks Tuck for your careful analysis. Now you see why I am *not* the
right person to propose the detailed (and no doubt delicate) fix. Your
wording proposal change seems right to me (but I am probably not the
right one to carefully vet such a proposal either :-)
****************************************************************
From: Robert Dewar
Sent: Thursday, May 11, 2000 4:37 AM
Note that I definitely agree we should NOT change the reference manual
here if we cannot come up with a simple change. But I think it is worth
trying a little harder to do so, since this is really otherwise quite
a surprising result, and I partiuclarly dislike resolution depending
on whether something is a general access type or not. It is really nasty
that adding ALL as a keyword should introduce ambiguities.
(at least that's my understanding of the *current* rules).
****************************************************************
From: Pascal Leroy
Sent: Thursday, May 11, 2000 5:05 AM
No, I think that the current rule is that ALL has no effect on name resolution.
Our compiler (and maybe yours, if I am reading Randy's messages correctly)
currently uses ALL when doing name resolution, but that's clearly a bug that
will have to be fixed.
****************************************************************
From: Robert Dewar
Sent: Thursday, May 11, 2000 5:20 AM
OK, if I misunderstand this, then fine, I am less concerned!
****************************************************************
From: Robert A Duff
Sent: Thursday, May 11, 2000 9:18 AM
Randy,
> One question, though, how does this work if the prefix is overloaded? That
> is, given the third example in my original message, is it legal or illegal
> (and why?)
I've deleted that message.
> Yes, of course. (You don't think I make these things up, I hope?)
I wasn't trying to accuse you of making things up. ;-) I thought I must
have misunderstood, or misremembered, what you said, because it seems
like a compiler would have to go out of its way to get this wrong.
>... All but
> one of the compilers I tried failed to detect the error in the second
> example in my original posting. And I thought you told me that your compiler
> failed that test as well.
It failed the B test as a whole, but it gets that part right.
This is the part about Zup, right?
We get:
227 Result20 : Float := Zup (Temperature'access); -- ERROR: Ambiguous
*
*****Error: LRM:8.6(31) Expression is ambiguous when interpreted as an
***** expression of the expected type Float, Returning first
***** interpretation
*
*****Error: LRM:3.10.2(24) The expected type for X'ACCESS, where X denotes an
***** aliased view of an object, must be a general access type,
***** Continuing
228 Result21 : Float := Zup (Float_Ptr'(Temperature'access)); -- OK
229
230 Result22 : Float := Zup (Temperature'Unchecked_Access); -- ERROR: Ambiguous
*
*****Error: LRM:8.6(31) Expression is ambiguous when interpreted as an
***** expression of the expected type Float, Returning first
***** interpretation
*
*****Error: LRM:3.10.2(24) The expected type for X'ACCESS, where X denotes an
***** aliased view of an object, must be a general access type,
***** Continuing
231 Result23 : Float := Zup (Float_Ptr'(Temperature'Unchecked_Access)); -- OK
> Specifically:
> Example 1 Example 2
> GNAT 3.13a: No error No error
> Apex 3.0.2b: Error No error
> Janus/Ada 3.1.2: No error Error
>
> Of these three, only Janus/Ada matches Tucker's proposed wording. (And given
> it's market share, we probably can ignore it.)
>
> The reason some ACATS test is desperately needed here is exactly that the
> compilers all differ in what they allow and reject. If we change the
> language, then I would change the test(s) accordingly (and issuing them
> after the AI is approved by WG9) -- but I think it is a crime to let
> compilers vary all over the map here.
Yes, whatever we decide on this, the ruling should not allow
implementations to differ, and the ACATS should enforce the ruling.
I would probably be willing to volunteer to write the test;
let me know (if and when we get to that point).
****************************************************************
From: Pascal Leroy
Sent: Thursday, May 11, 2000 2:50 AM
> I think the difference between pool-specific and general access types
> should *not* be used to resolve these things, and the above wording
> achieves that. Randy, is it really true that some compilers use the
> pool-specific/general distinction to resolve these cases? Which ones?
We do. Somebody was confused and considered that the second sentence of RM95
3.10.2(24) was a name resolution rule, which obviously it isn't. I'll fix this,
as there is clearly a consensus that this information should not be used for
name resolution.
****************************************************************
From: Randy Brukardt
Sent: Thursday, May 11, 2000 6:57 PM
To bring the discussion back to Tuck's wording.
In my original message, I had given an example where the prefix of the 'Access
was overloaded. Gary and I, at least, agree that we don't want to try to resolve
this expression, but I'm not sure how to get there. And Tuck's wording seems to
assume that the prefix is not overloaded (which would break access to subprogram
types).
Here is my object example from my original posting:
type Int_Ptr is access all Integer;
type Char_Ptr is access all Character;
type Float_Ptr is access all Float;
function Zap (Val : Int_Ptr) return Float;
function Zap (Val : Float_Ptr) return Float;
function Zop return Int_Ptr;
function Zop return Char_Ptr;
Resultx : Float := Zap (Zop.all'access);
This expression has a unique resolution if we use everything we know. But to
allow it means giving up on the "single access type" wording, which we need to
insure that 'access can't be used in contexts where no particular type is
implied (i.e. type conversions).
Tucker's wording (which I will repeat for those of us who've forgotten it
already...:-):
For an attribute_reference with attribute_designator Access (or
Unchecked_Access -- see 13.10), the expected type shall be
a single access type whose designated type covers the type of
the prefix, or whose designated profile is type conformant
with that of the prefix.
So what is the type of the prefix (Zop.all) in the example above? It is either
Integer *or* Character. One way to handle this is to interpret this a
chicken-and-egg rule; if that's done, my example does in fact resolve and is
legal. (By chicken-and-egg rule, I mean that we really don't know the answer; we
simply apply all of the rules at once to get the answer. Resolution is very much
like this anyway.)
Note that the access to subprogram case already uses the designated profile of
the expected access type to resolve the prefix (the second sentence of
3.10.2(2)). We certainly don't want to change that behavior.
Of course, using "single access type" in this way is a real fudge (because we do
allow sets of types as long as only one matches any possible interpretation of
the prefix). But we need that to disallow 'access in contexts where a specific
type can't be identified (such as type conversions).
Gary has proposed "maybe an extra rule is needed to say that the prefix shall
only have a single interpretation". However, that doesn't work for the
access-to-subprogram case; that is specifically designed to allow overloaded
prefixes.
An example for that:
procedure Foo (A : in Integer);
procedure Foo (B : in Float);
type Access_Single_Int_Proc is access procedure (A : in Integer);
P : Access_Single_Int_Proc := Foo'access; -- OK.
Foo'access is legal now, and any wording we adopt had better allow it to stay
that way.
A question for Tucker: is your wording intended to replace the entire paragraph?
That is, including the second sentence, and the "never an implicit conversion"
phrasing? I don't see a real problem with that, but it does extend the
resolution still further.
I guess I don't object to Tucker's rule, although the corner cases of it may be
more work that they are worth. OTOH, I suppose I could agree not to test them in
the ACATS.
Randy.
****************************************************************
From: Tucker Taft
Sent: Thursday, May 11, 2000 7:17 PM
Randy Brukardt wrote:
>
> > > Perhaps something like this would work for 3.10.2(2):
> > >
> > > Name resolution rules:
> > >
> > > For an attribute_reference with attribute_designator Access (or
> > > Unchecked_Access -- see 13.10), the expected type shall be
> > > a single access type whose designated type covers the type of
> > > the prefix, or whose designated profile is type conformant
> > > with that of the prefix.
> >
> > Thank you, Tucker. I tried to come up with wording today, and failed.
> > The above sounds exactly right, if we want to make this language
> > change. I suppose I could go along with this language change; I'm open
> > to either choice at this point.
>
> On first glance, this looks pretty good. It clearly solves most of the
> problems by leaving the "single access type" wording, which we need to avoid
> using 'Access in type conversions.
>
> One question, though, how does this work if the prefix is overloaded? That
> is, given the third example in my original message, is it legal or illegal
> (and why?)
Overloading seems OK in the prefix. After all, we already allow the prefix to
be overloaded when creating an access-to-subp value. From an implementation
point of view, you bubble up one or more "universal" access-to-type/profile
interpretations, and then complain if you get all the way to the top and you
still have any ambiguity. On the way back down, you check to see whether the
access type ultimately chosen uniquely selects one interpretation of the prefix
using only the type matching, and presuming it does, you then enforce the other
legality rules. The current implementation of access-to-subp has to work pretty
much the same way, since it is possible to via "use" clauses have so much
ambiguity in the prefix that even knowing the specific access-to-subp type won't
resolve it, and you need to report this fact on the way "down".
If the above is confusing, I could provide some concrete examples.
In any case, from my perspective, trying to outlaw overloading of the prefix is
unnecessary. I think the proposed rule works even if the prefix is overloaded.
****************************************************************
From: Robert Dewar
Sent: Thursday, May 11, 2000 7:20 PM
Tuck's wording seems fine to me, although I hesitate to label this as
an expert opinion :-) Certainly it seems to take care of the case I
was concerned about. So the only issue is whether this is troublesome
from any point of view.
****************************************************************
From: Tucker Taft
Sent: Thursday, May 11, 2000 10:11 PM
Randy Brukardt wrote:
>
> To bring the discussion back to Tuck's wording.
>
> In my original message, I had given an example where the prefix of the
> 'Access was overloaded. Gary and I, at least, agree that we don't want to
> try to resolve this expression, but I'm not sure how to get there.
I don't see why you don't want to resolve this.
> ... And
> Tuck's wording seems to assume that the prefix is not overloaded (which
> would break access to subprogram types).
I admit that the wording *could* be interpreted that way, but that would be
wrong ;-). The "shall be a single type" wording really is not very different
from the usual name resolution rules. You can pretty much ignore the "single"
part of the sentence, except for the added restriction of 8.6(27) disallowing
use as the operand of a type conversion. The key thing is that there is a
clearly specified amount of information that bubbles out of the construct. In
the case of an aggregate, what bubbles out is that it is a composite non-limited
object. In the case of an allocator, what bubbles out is that the designated
type must cover the type given in the allocator. Note that with an allocator
like new T, the possible access types include access-to-T as well as
access-to-T0'Class where T0 in any ancestor of T. This whole group of
possibilities needs to "bubble up" from the allocator.
Allowing the prefix of 'Access to be overloaded simply makes the set of
acceptable access types being bubbled up more complicated, but it still can be
thought of as a "class" for the purposes of 8.6(27). And context has to pick
just one of these access types, without getting any more information out of the
attribute ref. Of course, there is not much more information that could be
interesting, so the wording I proposed is not substantially different than
simply saying:
For an attribute_reference with attribute_designator Access (or
Unchecked_Access -- see 13.10), the expected type shall be
an access type whose designated type covers the type of -- NOTE: "single" omitted
the prefix, or whose designated profile is type conformant
with that of the prefix.
Followed by a special rule that blah'access may not be an operand of a type
conversion.
In retrospect, most of the wording of 8.6(27) is unnecessary, other than the
part disallowing use of these kinds of constructs as operands of type conversion
or in contexts where any type in a class is allowed. The special wording is
unnecessary because normal overloading resolution rules will require there be
only one interpretation of the context that matches the type requirements
bubbling up from the construct.
The key point is we want the context to expect a particular type, not just
specify some generic requirement for a type in some class, which might mean we
have to search all accessible packages for a unique type that meets both the
"bubbling up" requirements and the contextual requirements. So that is really
all the word "single" is there for. It doesn't mean there is no overloading
inside or outside the construct. Despite my earlier claims to the contary, the
usual chicken-and-egg analysis is still necessary, e.g. in the case of
allocators. For example, the following contextual overloading is legal even
though the "single" wording applies to allocator resolution:
type NT is new T with null record;
procedure Q(X : access T'Class; Y : Integer);
procedure Q(X : access NT'Class; Y : Float);
...
Q(new NT, 2); -- allocator resolves to "access T'Class"
>
> Here is my object example from my original posting:
>
> type Int_Ptr is access all Integer;
> type Char_Ptr is access all Character;
> type Float_Ptr is access all Float;
>
> function Zap (Val : Int_Ptr) return Float;
> function Zap (Val : Float_Ptr) return Float;
>
> function Zop return Int_Ptr;
> function Zop return Char_Ptr;
>
> Resultx : Float := Zap (Zop.all'access);
>
> This expression has a unique resolution if we use everything we know. But to
> allow it means giving up on the "single access type" wording, which we need
> to insure that 'access can't be used in contexts where no particular type is
> implied (i.e. type conversions).
I don't agree we need to abandon the "single access type" wording. As mentioned
above, the point of the "single ... type" requirement is that the context
must not expect just any type in a class, it must instead expect particular
types. For access types, I think that really just outlaws the use of
type conversion. Even an expected type of "access T'Class" would be OK,
since that is a particular, albeit anonymous, type.
Other contexts that don't require particular types are things like the
initializer for a named number, the bounds of an integer type definition,
the condition of an IF statement, etc., none of which are relevant to access types.
(In Ada 95, there are fewer of these contexts because places like the operand of
'Val have a particular type as their expected type, namely universal_integer.
Of course numeric literals don't have the "single type" rule anyway, so this use
of universal_integer is not relevant to this analysis.)
> ...
>
> A question for Tucker: is your wording intended to replace the entire
> paragraph? That is, including the second sentence, and the "never an
> implicit conversion" phrasing? I don't see a real problem with that, but it
> does extend the resolution still further.
The "never an implicit conversion" rule is actually redundant with 4.1.4(6), so
it is not strictly necessary to repeat it. However, we found it friendly to do
so before, and we don't want to give the appearance of a change. So here is a
way to retain it (and in fact, be more symmetrical in our redundancy ;-):
For an attribute_reference with attribute_designator Access (or
Unchecked_Access -- see 13.10), the expected type shall be
a single access type whose designated type covers the type of
the prefix, or whose designated profile is type conformant
with that of the prefix. The prefix of such an attribute_reference
is never interpreted as an implicit_dereference or parameterless
function_call (see 4.1.4).
The last sentence is bracketed in the AARM, since it is redundant with 4.1.4(6).
>
> I guess I don't object to Tucker's rule, although the corner cases of it may
> be more work that they are worth. OTOH, I suppose I could agree not to test
> them in the ACATS.
I would be surprised that the corner cases would be harder to resolve. Of
course, bugs are possible, but I would rather see a test case that exercises all
of the crazy cases, and have someone object if they have real heartburn
supporting it. I wouldn't normally feel this way, but since we are making this
change to bring all the compilers into agreement in an area where they seem to
have wandered off in different directions, let's go all the way.
Here is a crazy case, for example, that we might as well include:
type P is access procedure;
type A is access Integer;
procedure Z(X : P; Y : Integer);
procedure Z(X : A; Y : Float);
function F return P;
function F return A;
...
Z(F.all'access, 2); -- F.all'access resolves to type P.
****************************************************************
From: Robert A Duff
Sent: Friday, May 12, 2000 10:15 AM
> In my original message, I had given an example where the prefix of the
> 'Access was overloaded. Gary and I, at least, agree that we don't want to
> try to resolve this expression, but I'm not sure how to get there. And
> Tuck's wording seems to assume that the prefix is not overloaded (which
> would break access to subprogram types).
When I first read Tuck's wording, I interpreted it to mean that the
prefix can be overloaded, and the designated type of the access type can
be used to resolve it. The compiler has to consider all possible
interpretations, and figure out the right one -- that's how overload
resolution always works.
For example, here's a plain-vanilla case of overload resolution:
procedure P(X: Integer);
procedure P(X: Boolean);
function F return Integer;
function F return Character;
P(F);
The RM says that the expected type for the actual parameter of P is the
type of the formal. But there are *two* formals to consider -- one is
Integer, one is Boolean. So we read the arcane mutterings in 8.6, and
find out that we need to consider both. So the above resolves just
fine.
Tuck's new wording for 3.10.2.(2) should be read the same way.
> Here is my object example from my original posting:
>
> type Int_Ptr is access all Integer;
> type Char_Ptr is access all Character;
> type Float_Ptr is access all Float;
>
> function Zap (Val : Int_Ptr) return Float;
> function Zap (Val : Float_Ptr) return Float;
>
> function Zop return Int_Ptr;
> function Zop return Char_Ptr;
>
> Resultx : Float := Zap (Zop.all'access);
I think the compiler should be required to resolve the above. And I
think Tuck's wording achieves that, if you pay attention to 8.6. The
"type of the prefix" has to be interpreted as "the two possible types of
the two possible prefixes", each considered separately.
> A question for Tucker: is your wording intended to replace the entire
> paragraph? That is, including the second sentence, and the "never an
> implicit conversion" phrasing? I don't see a real problem with that, but it
> does extend the resolution still further.
I thought Tuck's wording replaced just the *first* sentence of
3.10.2(2). But the "never an implicit conversion" phrasing should be
retained -- it is square-bracketed in the AARM, which indicates that it
follows from something else. The actual rule is in 4.1.4(6).
It seems to me that the second sentence is still needed, and we also
need an anaogous sentence for the access-to-object case, now that we
allow overloading of the prefix:
If the expected type is an access-to-object type, then the expected
type of the prefix is the designated type of the access type.
Add the above after Tuck's wording, and then: "Similarly, [second
sentence of existing RM para]."
> I guess I don't object to Tucker's rule, although the corner cases of it may
> be more work that they are worth. OTOH, I suppose I could agree not to test
> them in the ACATS.
I strongly believe we should test this sort of thing -- ESPECIALLY the
corner cases. This is the sort of thing that can cause very real
portability problems.
I find it *very* distasteful to spend a lot of energy making good rules,
and then turn around and say, "we don't really mean it".
The *only* time we should agree to avoid testing something is when
there's a pathology in the language, and we can't fix it for some
reason. Pathologies are language bugs. We shouldn't call something a
pathology just because it seems like a fairly rare combination of
features, and/or is hard to implement. Compiler writers (that's many of
us) tend to be far too willing to label something a pathology, in my
opinion (which is why I'm ranting about this now ;-)).
Besides, I don't see any particular implementation difficulty here;
we're basically doing access-to-object the same way access-to-subprogram
is already done. And we've already got some compilers that (naughtily)
implement it that way!
I say, if we're not willing to test what the rules say, then we've
designed the wrong rules!
****************************************************************
From: Robert A Duff
Sent: Friday, May 12, 2000 1:14 PM
Tucker mentioned to me this morning that the NOTE at
RM-4.1.4(14) will be wrong if we adopt the new rule. That should be
fixed, if a new RM is being produced.
Also, the AARM-3.10.2(2.a) will be wrong. I don't know how Randy wants
to deal with the AARM. If I were him, I would not modify the AARM
annotations at all, but merely add a new annotation saying the above is
obsolete. It's not really ARG's job to maintain the AARM, but I suspect
Randy's tools will be able to turn it into a more modern formatting
language more-or-less "for free". (Free speech *and* free beer.)
*************************************************************
From: Randy Brukardt
Sent: Friday, May 12, 2000 12:02 PM
OK, merging Bob's and Tuck's suggestions, we get the following for the
revised wording of the complete paragraph 3.10.2(2):
For an attribute_reference with attribute_designator Access (or
Unchecked_Access -- see 13.10), the expected type shall be
a single access type whose designated type covers the type of
the prefix, or whose designated profile is type conformant
with that of the prefix. [The prefix of such an attribute_reference
is never interpreted as an implicit_dereference or parameterless
function_call (see 4.1.4).] If the expected type is an access-to-object
type, then the expected type of the prefix is the designated type of the
access type. Similarly, if the expected type is an access-to-subprogram
type, then the expected profile of the prefix is the designated profile
of the access type.
Any objections or technical problems? If not, I'll rewrite the AI to use
this wording. Then we can consider it at the next meeting.
BTW, I've initiated a compiler survey in order to have a stronger
justification for making this change. So far, most of the compilers reported
are closer to the new wording than to the existing RM.
*************************************************************
From: Tucker Taft
Sent: Friday, May 12, 2000 3:01 PM
> Any objections or technical problems?
It is getting a bit verbose. Perhaps we could shorten the last two
sentences to:
The designated type/profile of the expected type of the
attribute_reference is the expected type/profile for the prefix.
*************************************************************
From: Robert A Duff
Sent: Friday, May 12, 2000 3:52 PM
> It is getting a bit verbose. Perhaps we could shorten the last two
> sentences to:
>
> The designated type/profile of the expected type of the
> attribute_reference is the expected type/profile for the prefix.
I like it.
And now that we have wording that says what we think it says, we can
talk about whether we should change the language in this way.
My first reaction to this issue was "No way! Rules are rules! Make all
those evil compiler writers who did it wrong fix it. (Including us.)"
But now I'm inclined to say we should make the change. I think it
improves the language. Also, as Robert Dewar points out, some people
are depending on this compiler bug, so we should probably declare it to
be a non-bug.
*************************************************************
From: Randy Brukardt
Sent: Friday, May 12, 2000 6:05 PM
> > It is getting a bit verbose. Perhaps we could shorten the last two
> > sentences to:
> >
> > The designated type/profile of the expected type of the
> > attribute_reference is the expected type/profile for the prefix.
>
> I like it.
Well, I don't. I don't know quite what to make of the slashes. If I mentally
replace them by "or", it makes more sense -- but then why not say that?
The designated type or profile of the expected type of the
attribute_reference is the expected type or profile for the prefix.
> And now that we have wording that says what we think it says, we can
> talk about whether we should change the language in this way.
>
> My first reaction to this issue was "No way! Rules are rules! Make all
> those evil compiler writers who did it wrong fix it. (Including us.)"
>
> But now I'm inclined to say we should make the change. I think it
> improves the language. Also, as Robert Dewar points out, some people
> are depending on this compiler bug, so we should probably declare it to
> be a non-bug.
While I think the basic idea is a good one, I don't think we can get around
the fact that this wording is an *extension* to the language. The behavior
of existing compilers don't fully support Tucker's wording.
With Bob's help, I've tested the two overloading examples (mine and
Tucker's) on 4 popular compilers (well, 3 popular compilers and Janus/Ada.
:-) Indeed, all four compilers choke on my example, even when qualified,
presumably because they don't support overloading in the prefix (a couple of
the compilers put out a message to that effect). [GNAT seems to have a bug
here, as it seems to select one interpretation of the prefix, ignoring any
others silently.]
The access-to-subprogram type in Tucker's example seems to confuse matters.
The compilers seem to prefer either the object or the subprogram prefix; but
no compiler allows both.
I've also found out from Joyce that the DDCI compiler in fact implements the
RM rules. (It too has a bug and misses a couple of errors, but not the same
ones as Rational Apex). So the compiler survey is now less clear cut. (I'm
still waiting for responses from other compiler vendors.)
The overloading implications of Tucker's wording may take some effort to get
right, and may be quite difficult in some implementations. Moreover, it is a
clear extension to practice in any compiler that I've got a result for.
I would feel better with wording which did not require support for
overloading resolution in the prefix of object'access. I'm not sure that
such wording is possible.
If we feel we have to have overloading resolution in the prefix to make this
work (and I currently think we do), then I fear we have a clear extension --
we can't even rely on the behavior of current compilers to justify the
change.
In that case, the only reasonable choices are to confirm the RM (which
Robert doesn't like for possibly legitimate reasons), or to make the change
in Ada 0y and emasculate the ACATS test to leave only cases that neither
conflict with the current RM or revised wording (which would leave Ada users
with the portability problem for at least 5 more years). Both bad choices.
*************************************************************
From: Tucker Taft
Sent: Friday, May 12, 2000 6:47 PM
I agree with Bob. I think we should make the change, and
add a test to ACATS that does its best to get all compilers
to handle the resolution of 'Access the exact same way.
*************************************************************
From: Robert Dewar
Sent: Friday, May 12, 2000 7:43 PM
But the test could only be advisory pending WG9 accepting the relevant AI
I suppose.
*************************************************************
From: Robert A Duff
Sent: Saturday, May 13, 2000 10:41 AM
Randy proposes:
> The designated type or profile of the expected type of the
> attribute_reference is the expected type or profile for the prefix.
That's sound fine, too.
*************************************************************
From: Tucker Taft
Sent: Monday, May 15, 2000 7:54 AM
Randy Brukardt wrote:
> ...
> While I think the basic idea is a good one, I don't think we can get around
> the fact that this wording is an *extension* to the language. The behavior
> of existing compilers don't fully support Tucker's wording.
I don't think this really is the issue. Yes it is certainly an extension.
However, we have concluded that few compilers support the existing wording,
and we recognize some clear problems with the wording as in the RM as far
as functionality. It would never be appropriate to expect all compilers to
magically implement some well-stated different rule, since the current behavior
is due to a series of oversights or laxness during implementation. I suggest
we ask implementors to evaluate the implementation difficulties of the general
overloading solution. In my experience, it is usually easier to allow arbitrary
overloading than to enforce particular restrictions. Furthermore, the kind
of overloading we are talking about is very similar to the kind of overloading
that occurs in many other constructs.
Hence, I suggest we take what is the cleanest rule (which I feel is roughly
where we are now in our wording), and run it up the flagpole. Trying to fit the
wording to the existing behavior of some compilers is bound to produce a
kludgier rule, and likely be harder for some compilers than others to get right.
This seems like a lose-lose. Once we have more input from implementors, the ARG
can decide whether to approve the change. The fact that it is an "extension" is
not really relevant in my view, presuming we approve it and have a good test for
it. Note that in Ada 83 we approved extending the character set from 128 to 256
characters, a much more significant change.
Clearly any ACATS enforcement of a change like this, presuming it is approved,
has to be phased in...
*************************************************************
From: Robert Dewar
Sent: Monday, May 15, 2000 10:26 AM
<<> While I think the basic idea is a good one, I don't think we can get around
> the fact that this wording is an *extension* to the language. The behavior
> of existing compilers don't fully support Tucker's wording.
>>
Well lots of AI's in the past have been language extensions (to be honest)
*************************************************************
From: Randy Brukardt
Sent: Wednesday, May 31, 2000 4:56 PM
I sent my super-duper ACATS test for this issue to the vendors whose
compilers I don't currently have access to to get a better feel for where
the majority of compiler's stand.
Example 1 is the basic "use-of-the-prefix-type" resolution case. (This
should fail given the RM wording and succeed given the change proposed in
AI-235.)
Example 2 is the test of a conflict between a general access type and a
pool-specific access type. This should fail; there is no intent to change
this.
Example 3 is the resolution of an overloaded prefix. This should fail
(trivially) given the RM wording and succeed given the change proposed in
AI-235.)
Example 4 is similar to example 3, but it uses the type of an additional
parameter to resolve. This should have the same results as example 3. [I
didn't provide Examples 3&4 to all of the vendors, so not all compilers have
results for these cases.]
Here is an updated list:
Example 1 Example 2 Example 3 Example 4
GNAT 3.13a: No error No error Error* Error*
Apex 3.0.2b: Error No error Error* Error*
Janus/Ada 3.1.2: No error Error Error* Error*
AverStar adacsrc 3.317: No error Error Error* Error*
DDCI: Error Error*
OcSystems 4.1: No error Error
* Notes:
GNAT 3.13a apparently resolves overloaded object'access prefixes by
arbitrarily selecting the last overloaded routine as the solution. Thus some
expressions resolve, and others do not. This seems to be a bug, it would be
better to reject all such expressions.
Janus/Ada 3.1.2 rejects object'access prefixes which cannot be uniquely
resolved without context. (As I recall, allowing the use of some context for
access-to-subprograms was very painful, but I don't know if the extension
would be a problem.) It gets confused when object'access is overloaded with
subprog'access.
Apex 3.0.2b rejects object'access prefixes which cannot be uniquely resolved
without context. It seems to prefer object'access over subprog'access when
they both are overloaded, confusing Example 4.
Averstar 3.317 rejects object'access prefixes which cannot be uniquely
resolved without context. It seems to prefer subprog'access over
object'access when they both are overloaded, confusing Example 4 (and
exactly the reverse of Apex).
DDCI's compiler almost matches the RM, but allows overloading between
access-to-subprogram types and object types.
----
The Janus/Ada, Averstar, OcSystems, and GNAT compilers (and presumably the
Aonix and Greenhills compilers as well) come close to Tucker's proposed
wording. Janus/Ada and GNAT have some minor differences in handling
overloading, and GNAT also fails the "general vs. pool-specific" issue, but
these aren't significant.
The Rational Apex and DDCI compilers come close to the existing RM wording,
so
they would have to change the most. But that would be painless to their
users, while changing all of the others could very well be painful to their
users.
Note that no compilers tested handle the overloading cases properly (that
is, as suggested by Tucker's wording).
Randy.
*************************************************************
From: Gary Dismukes
Sent: Wednesday, May 31, 2000 7:43 PM
A comment on part of the !discussion section:
> To work around the problem caused by the original RM rule, a named access
> type has to be introduced, so that it can be used in a qualified expression:
>
> function Do_It (Obj : Int_Ptr) return Boolean;
>
> if Do_It (Int_Ptr'(Value'Access)) then ... -- OK.
>
> But this is not quite equivalent, because the accessibility rules for
> anonymous access types is different from named access types. Thus, the user
> usually will have to change to using 'Unchecked_Access as well.
What you say is true, but the above is a little confusing, because
it's not necessary to change the type of the formal parameter. The
formal can be left as "Obj : access Integer", only the actual in
the call needs to be changed for this workaround. So I suggest
deleting the function spec with the Int_Ptr parameter, and then
you should clarify that it's the conversion implicit in the qualified
expression that changes the accessibility semantics. (Of course,
as long as the extra access type is declared at the same level as
the call, then this workaround should have the same accessibility
semantics, i.e., no access check needed, but it's obviously a bit
messy and error-prone to have to declare a local access type.)
*************************************************************
From: Randy Brukardt
Sent: Wednesday, May 31, 2000 10:27 PM
> So I suggest
> deleting the function spec with the Int_Ptr parameter,
OK; I didn't realize that would work (although it obviously does).
> and then you should clarify that it's the conversion implicit
> in the qualified expression that changes the accessibility semantics.
This seems as confused as my original statement. The accessibility check is
part of the 'Access attribute (3.10.2(28-29)), and its the expected type of the
attribute that determines the check made. Using the qualified expression
changes the expected type to the named type, and that changes the accessibility.
There is an implicit conversion to the "original" weaker checks of anonymous
access types when the qualified expression is converted, but that won't do
anything interesting in this case.
>(Of course, as long as the extra access type is declared at the same level as
> the call, then this workaround should have the same accessibility
> semantics, i.e., no access check needed, but it's obviously a bit
> messy and error-prone to have to declare a local access type.)
I changed the paragraph in question to:
To work around the problem caused by the original RM rule, a named access type
has to be introduced, so that it can be used in a qualified expression:
if Do_It (Int_Ptr'(Value'Access)) then ... -- OK.
But this is not quite equivalent, because the accessibility rules for anonymous
access types is different from named access types. (The use of the qualified
expression changes the accessibility check for the Access attribute from the
anonymous type to the named type.) Thus, the user will have to declare
an access type in the scope of each call, or will have to change to using
'Unchecked_Access.
Does that meet your concern?
(Since I forgot to check it in earlier, this will be in today's version of the
AI.)
*************************************************************
From: Tucker Taft
Sent: Thursday, June 01, 2000 8:30 AM
Looks good to me (modulo Gary's suggestion about the example).
*************************************************************
From: Ed Schonberg
Sent: Thursday, June 01, 2000 8:27 PM
Randy's test now passes on gnat:
nile{schonber}65: gnatmake -I../ c3a200x
gcc -c -I../ c3a200x.adb
gcc -c -I../ c3a200xa.adb
gcc -c -I../ report.adb
gnatbind -aO./ -aO../ -I- -x c3a200x.ali
gnatlink c3a200x.ali
nile{schonber}66: c3a200x
,.,. C3A200X ACVC 2.0 00-06-01 21:15:39
---- C3A200X Check that 'Access and 'Unchecked_Access attributes can use
the type of their prefix in resolving overloading..
==== C3A200X PASSED ============================.
This took about an hour of work, and added 50 lines to the front-end, so
needless to say we find this a perfectly implementable rule (and furthermore
one that will not force us to change all these overloaded prefixes in our own
run-time!).
*************************************************************
From: Pascal Leroy
Sent: Tuesday, June 06, 2000 7:22 AM
I have modified our compiler to implement AI-235:
varenne$ c3a200x
,.,. C3A200X ACVC 2.2 00-06-06 14:06:02
---- C3A200X Check that 'Access and 'Unchecked_Access attributes can use
the type of their prefix in resolving overloading..
==== C3A200X PASSED ============================.
It took me a bit less than a day, and the version control system tells me that I
have changed 272 lines (to be honest, these changes included fixing a bug in the
handling of the access-to-subprogram case that I noticed while reading the
code). So for us this was not a big change, even though we were originally
quite close to the RM.
I haven't run an entire ACVC yet, but I am noticing that we now fail test
b3a2016, which is not surprising since this test checks RM95 3.10.2(2). It
seems to me that vendors should be able to validate compilers which implement
AI-235, and therefore that this test should be removed from the suite. I'd like
to hear the ACAA's opinion on this.
*************************************************************
From: Randy Brukardt
Sent: Friday, June 16, 2000 6:21 PM
Pascal said:
> I haven't run an entire ACVC yet, but I am noticing that we
> now fail test b3a2016, which is not surprising since this
> test checks RM95 3.10.2(2). It seems to me that vendors
> should be able to validate compilers which implement AI-235,
> and therefore that this test should be removed from the
> suite. I'd like to hear the ACAA's opinion on this.
Randy responds (wearing my ACAA hat):
It was obvious to me the B3A2016 would have to be changed, because as long as
AI-235 is under consideration, testing cases that it might change (either way)
is wrong. OTOH, the test includes some useful cases (and I had added several
more useful cases more recently), and a B-Test is clearly needed along with a
C-Test (assuming AI-235 passes as is). So I created a version of the test with
all of the problematical cases commented out, and a variety of new cases.
I thought it best to wait a while before issuing the test (to see if AI-235
would be changed again), so I went on vacation rather than actually issuing it.
But I intend to do that next week.
Under the ACAA rules, this action will reset the required date, so the new test
won't be required until January 1st, 2001. Once WG9 approves AI-235, I'll issue
an improved version of the C-Test (at least, the name has to be changed), and a
revised version of the new B-Test (with the commented out cases replaced,
either as "OK" or "Error", as needed).
Randy Brukardt.
ACAA Technical Agent.
*************************************************************
From: Pascal Leroy
Sent: Saturday, June 10, 2000 2:07 AM
> !wording
>
> Replace 3.10.2(2) with:
> For an attribute_reference with attribute_designator Access (or
> Unchecked_Access -- see 13.10), the expected type shall be
> a single access type whose designated type covers the type of
> the prefix, or whose designated profile is type conformant
> with that of the prefix. [The prefix of such an attribute_reference
> is never interpreted as an implicit_dereference or parameterless
> function_call (see 4.1.4).] The designated type or profile of the
> expected type of the attribute_reference is the expected type or
> profile for the prefix.
I believe there is a serious problem with this wording. It seems to me that
we have lost the ability to use 'Access as a controlling parameter of a
dispatching call. Essentially, the changes that we did in AI 127 should
have been taken into account when writing the wording section for AI 235.
Consider the following code fragment:
type T is tagged null record;
function F (X : access T) return Boolean;
X : T;
Y : T'Class := X;
Z : Boolean := F (Y'Access);
It appears that the attribute Access in the declaration of Z is illegal
according to the new wording. The expected type for Y'Access is the
anonymous access type access T, and the designated type T does not cover the
type of the prefix, T'Class, so the new 3.10.2(2) makes the attribute
illegal. We don't even get as far as looking at RM95 8.6(22-25).
*************************************************************
From: Randy Brukardt
Sent: Friday, June 16, 2000 6:58 PM
Yes, I agree. AI-127 is part of the corrigendum, so it has priority here.
Fixing this wording is very hard (which probably why you didn't attempt it!).
> Consider the following code fragment:
>
> type T is tagged null record;
> function F (X : access T) return Boolean;
>
> X : T;
> Y : T'Class := X;
> Z : Boolean := F (Y'Access);
>
> It appears that the attribute Access in the declaration of Z
> is illegal according to the new wording.
He-he: it is illegal according to *any* wording, original, corrigendum, or
AI-235. Because Y isn't aliased. :-)
I assume you meant:
Y : aliased T'Class := X;
> The expected type for Y'Access is the anonymous access type access T,
> and the designated type T does not cover the type of the prefix, T'Class,
> so the new 3.10.2(2) makes the attribute illegal. We don't even get as
> far as looking at RM95 8.6(22-25).
I don't know what 8.6 has to do with it. The change for AI-127 (according to the
corrigendum) is in 3.10.2(27) (with a small change to 3.10.2(24) to define
@i<D>):
* If @i<A> is a named access type and @i<D> is a tagged type, then the
type of the view shall be covered by @i<D>; if @i<A> is anonymous and
@i<D> is tagged, then the type of the view shall be either @i<D>'Class
or a type covered by @i<D>; if @i<D> is untagged, then the type of the
view shall be @i<D>, and @i<A>'s designated subtype shall either
statically match the nominal subtype of the view or be discriminated
and unconstrained;
The change to 3.10.2(2) makes most of this unnecessary; it just echoes the
resolution rule. (We do need the untagged part.)
The best fix I can come up with is (but it's incredibly awkward):
Replace 3.10.2(2) with:
For an attribute_reference with attribute_designator Access (or
Unchecked_Access -- see 13.10), the expected type shall be
a single access type whose designated type covers the type of
the prefix, or, if the type of the prefix is D'Class, whose designated
type is D, or whose designated profile is type conformant with that of
the prefix. [The prefix of such an attribute_reference is never
interpreted as an implicit_dereference or parameterless function_call
(see 4.1.4).] The designated type or profile of the expected type of the
attribute_reference is the expected type or profile for the prefix.
With this scheme, we'd probably be best off leaving 3.10.2(27) alone (we still
need the rule about named vs. anonymous access types, along with the untagged
type rule). I don't think we want to try to use whether or not the type is
anonymous in resolution, even though it still affects legality.
We can't name the type D in 3.10.2(2) like we did in 3.10.2(27), because
access-to-subprogram types also come through 3.10.2(2), and they don't have a
designated type.
I'd prefer to use words for the "D'Class" garbage, but I can't find any that
mean what I need: "...covers the type of the prefix or is the xxxx type of the
prefix if the prefix has a classwide type, or whose...". What the heck *is* the
name for the type represented by D in D'Class for a classwide type? The closest
I can come is "specific" type, but I don't think that is right. Perhaps there
isn't one, but perhaps there should be?
*************************************************************
From: Pascal Leroy
Sent: Tuesday, November 28, 2000 7:37 AM
During the last meeting, we came to an agreement on the name resolution
rules that should apply to the prefix of 'Access (and 'Unchecked_Access).
But it seems to me that we still need to fix the first sentence of RM95
3.10.2(27) which reads (in the corrigendum):
"If A is a named access type and D is a tagged type, then the type of the
view shall be covered by D; if A is anonymous and D is tagged, then the type
of the view shall be either D'Class or a type covered by D; ..."
The distinction between named and anonymous access types was introduced as
part of AI95-00127 to permit dispatching. As written, this rule makes the
following code fragment illegal:
type T is tagged null record;
type A_T is access all T;
Y : aliased T'Class := T'(null record);
Z : A_T := Y'Access; -- ERROR
because A_T is a named access type and the type of Y (T'Class) is not
covered by T.
I believe that the distinction between named and anonymous access types
should be now removed from 3.10.2(27):
"If D is a tagged type, then the type of the view shall be either D'Class or
a type covered by D; ..."
*************************************************************
From: Randy Brukardt
Sent: Tuesday, November 28, 2000 4:45 PM
Pascal wrote:
> During the last meeting, we came to an agreement on the name resolution
> rules that should apply to the prefix of 'Access (and 'Unchecked_Access).
>
> But it seems to me that we still need to fix the first sentence of RM95
> 3.10.2(27) which reads (in the corrigendum):
>
> "If A is a named access type and D is a tagged type, then the type of the
> view shall be covered by D; if A is anonymous and D is tagged, then the type
> of the view shall be either D'Class or a type covered by D; ..."
>
> The distinction between named and anonymous access types was introduced as
> part of AI95-00127 to permit dispatching. As written, this rule makes the
> following code fragment illegal:
>
> type T is tagged null record;
> type A_T is access all T;
>
> Y : aliased T'Class := T'(null record);
>
> Z : A_T := Y'Access; -- ERROR
>
> because A_T is a named access type and the type of Y (T'Class) is not
> covered by T.
>
> I believe that the distinction between named and anonymous access types
> should be now removed from 3.10.2(27):
>
> "If D is a tagged type, then the type of the view shall be either D'Class or
> a type covered by D; ..."
This change seems to be only loosely related to AI-235. The point of the AI-235
is to allow the type of the prefix to be used in the resolution of 'Access. This
comment seems to be suggesting to allow more kinds of prefix to be allowed.
As Pascal noted, the current legality rule was created (in AI-127) to permit
dispatching operands to be 'Access or an allocator. It was not to allow more
(implicit) conversions in general. Thus, the rule was restricted to anonymous
access types, which must be a parameter, and which are likely to be controlling.
There doesn't seem to have been any reason that the rule of AI-127 couldn't have
applied to all access types; thus I have to assume that it was a conscious
decision (given that the wording is some much more complex this way).
Pascal's example does not contain any dispatching, so it is a different issue
than that implied by AI-127; and it clear that it is a different issue than
AI-235 as well. (If his proposed change is made, the example is legal whether or
not AI-235 is adopted.)
Note that AI-235 allows "If D is a tagged type, then the type of the view shall
be either D'Class or a type covered by D" in the resolution rule, as insisting
that the access type is anonymous would complicate the resolution rule with no
gain. It is not intending to allow prefixes not allowed currently, but simply to
allow prefixes (or the type of a parameter) to be overloaded.
Note that if Pascal's proposed change was adopted, 'Access and allocators would
be inconsistent as to the types allowed (4.8(3) has the same rule). If we make
the change, it should be made there as well.
That is, both of the following are illegal in the current standard, and I don't
see any reason to change one without changing the other:
> Z : A_T := Y'Access; -- ERROR:
> ZZ: A_T := new T'Class(Y); -- ERROR:
In any event, I don't see any reason to make this change in AI-235. I could see
making it a separate AI, but I guess I'd like to see a compelling reason for
the change. "Because we can" doesn't seem to be a good reason for language
design; we *can* implicitly convert *everything* to everything else, but we
know this is a bad idea.
*************************************************************
From: Tucker Taft
Sent: Tuesday, November 28, 2000 5:40 PM
Randy Brukardt wrote:
> ...
> Pascal's example does not contain any dispatching, so it is a different
> issue than that implied by AI-127; and it clear that it is a different issue
> than AI-235 as well. (If his proposed change is made, the example is legal
> whether or not AI-235 is adopted.)
> ...
> In any event, I don't see any reason to make this change in AI-235. I could
> see making it a separate AI, but I guess I'd like to see a compelling reason
> for the change. "Because we can" doesn't seem to be a good reason for
> language design; we *can* implicitly convert *everything* to everything
> else, but we know this is a bad idea.
I agree with Randy that we don't want to make this change.
In general, we only allow "implicit" conversion from T'Class
to T as part of dispatching. We definitely considered allowing
it in more cases during Ada 9X, but decided against for what
I am sure were good reasons at the time (though please don't
ask me to repeat them right now ;-).
See 3.9.2(9) for the rule that disallows the T'Class => T conversion
except as part of dispatching. Note that this is a case where overload
resolution allows the conversion, but a specific legality rule
disallows it. That is, the overload resolution rule is more permissive
than the legality rule.
As I think about it more, I am beginning to remember some of the
"good" reasons. Reading the AARM (3.9.2(9a)) also helps remind me.
Basically, converting from T'Class to T is a kind of "truncation." If
this is coupled with dispatching, there is no problem. However, when not
coupled with dispatching, it allows a potentially confusing
truncation to occur. I realize that with access types, no real
truncation is happening. However, conversion to specific ancestors
(as opposed to classwide ancestors) is in some cases privacy-breaking,
and we certainly don't want that to occur without an explicit
conversion visible in the code.
Now that I have mentioned these privacy-breaking conversions, I would
like to put in a request that we define a configuration pragma to outlaw
them, and perhaps make them obsolescent in Ada 200X. A privacy-breaking
conversion is any (non-dispatching) conversion from a class-wide type to
a specific type, or a conversion from a specific type to a specific ancestor
type when there is at least one private extension involved in the chain from
the ancestor to the descendant.
Such conversions are "privacy breaking" because the
operations on the target type might not preserve all
the invariants associated with the source object's (run-time) type.
If all the extensions between two types are visible record extensions,
then there can't be much of an invariant to be preserved anyway.
However, as soon as there is at least one private extension involved,
fields within that private extension might be required to be kept
in "sync" whenever components of the target/ancestor type are updated,
and this obviously couldn't be done by the operations of the ancestor
type.
For example, given:
type T is tagged ...
procedure Update(X : in out T);
type NT is new T with private;
procedure Update(X : in out NT);
. . .
Y : NT;
Z : T'Class := Y;
. . .
Update(T(Y)); -- This is privacy breaking
Update(T(Z)); -- So is this
Update(T'Class(Y)); -- This is OK, because it dispatches
Of course, "Update(T(Y));" would be allowed within the scope
of the full view of NT, because the extension is visible there,
and this kind of conversion is important to support the typical
"pass-the-buck" style of programming.
*************************************************************
From: Pascal Leroy
Sent: Wednesday, November 29, 2000 4:01 AM
> I agree with Randy that we don't want to make this change.
> In general, we only allow "implicit" conversion from T'Class
> to T as part of dispatching.
> ...
> Basically, converting from T'Class to T is a kind of "truncation." If
> this is coupled with dispatching, there is no problem. However, when not
> coupled with dispatching, it allows a potentially confusing
> truncation to occur. I realize that with access types, no real
> truncation is happening.
OK, I understand, that makes sense. Objection withdrawn.
*************************************************************
From: Pascal Leroy
Sent: Wednesday, November 29, 2000 5:30 AM
> See 3.9.2(9) for the rule that disallows the T'Class => T conversion
> except as part of dispatching. Note that this is a case where overload
> resolution allows the conversion, but a specific legality rule
> disallows it. That is, the overload resolution rule is more permissive
> than the legality rule.
Now that you have drawn my attention to 3.9.2(9), I believe that as written
now it defeats the purpose of AI95-00235. Consider:
type T is tagged null record;
function F (X : access T) return Boolean;
Y : aliased T'Class := T'(null record);
B : Boolean := F (Y'Access);
The AI tells us that (1) the expected type for Y'Access is the anonymous
"access T" and (2) the expected type for Y in Y'Access is T.
At this point the first sentence of 3.9.2(9) kicks in: the expected type for
Y is T, which is a specific tagged type, and Y is dynamically tagged, so
it's illegal.
Note that this happens because the prefix of 'Access now has an expected
type, while previously it had to be resolved independently of the context;
in other words, we have an implicit conversion of Y to T, and this implicit
conversion is not a controlling operand.
So I think that the first sentence of 3.9.2(9) needs to be revised along the
lines of:
"... unless it is a controlling operand in a call on a dispatching
operation, or the prefix of an Access or Unchecked_Access attribute which is
a controlling operand in a call on a dispatching operation."
But this is not quite right because the part about attributes should also
take into account attributes that appear in parenthesized expressions or
qualified expressions.
*************************************************************
From: Tucker Taft
Sent: Wednesday, November 29, 2000 8:40 AM
> So I think that the first sentence of 3.9.2(9) needs to be revised along the
> lines of:
>
> "... unless it is a controlling operand in a call on a dispatching
> operation, or the prefix of an Access or Unchecked_Access attribute which is
> a controlling operand in a call on a dispatching operation."
This may not be necessary, because the "controlling operand" in
the example you give above is in fact "Y", not "Y'Access," so the
first sentence of 3.9.2(9) already covers it. See 3.9.2(2), where it says:
... If the controlling formal parameter is an access parameter, the
controlling operand is the object designated by the actual parameter,
rather than the actual parameter itself. ...
>
> But this is not quite right because the part about attributes should also
> take into account attributes that appear in parenthesized expressions or
> qualified expressions.
Can you give some examples of these? I think the definition of
"controlling operand" solves these as well.
*************************************************************
From: Pascal Leroy
Sent: Wednesday, November 29, 2000 8:54 AM
> This may not be necessary, because the "controlling operand" in
> the example you give above is in fact "Y", not "Y'Access," so the
> first sentence of 3.9.2(9) already covers it. See 3.9.2(2), where it says:
>
> ... If the controlling formal parameter is an access parameter, the
> controlling operand is the object designated by the actual parameter,
> rather than the actual parameter itself. ...
I see. Missed that subtlety.
> > But this is not quite right because the part about attributes should also
> > take into account attributes that appear in parenthesized expressions or
> > qualified expressions.
>
> Can you give some examples of these? I think the definition of
> "controlling operand" solves these as well.
I was thinking of something like:
B : Boolean := F ((((Y'Access))));
but you're right, the above paragraph has the right effect in this case.
*************************************************************
From: Robert A Duff
Sent: Wednesday, November 29, 2000 9:38 AM
> In any event, I don't see any reason to make this change in AI-235. I could
> see making it a separate AI, but I guess I'd like to see a compelling reason
> for the change. "Because we can" doesn't seem to be a good reason for
> language design; we *can* implicitly convert *everything* to everything
> else, but we know this is a bad idea.
The language design principle for conversions is that conversions that
"make sense", and cannot lose information, and cannot fail at ruin time,
should be implicit. Others should be explicit (if allowed at all). By
"make sense", I mean not violating the type system -- converting apples
to oranges or whatever should be explicit.
Unfortunately, the above principle conflicts with the principle of
upward compatibility.
I like the typo "ruin time"; I think I'll leave it in. ;-)
*************************************************************
Questions? Ask the ACAA Technical Agent