Version 1.9 of ai05s/ai05-0090-1.txt
!standard 4.1.3(9.2/2) 08-10-21 AI05-0090-1/05
!standard 9.1(9.5/2)
!standard 9.4(11.4/2)
!class binding interpretation 08-02-04
!status Amendment 201Z 08-11-26
!status WG9 Approved 08-11-13
!status ARG Approved 7-0-1 08-06-21
!status work item 08-02-04
!status received 08-02-04
!priority Medium
!difficulty Medium
!qualifier Omission
!subject Ambiguities with prefixed views of synchronized primitives
!summary
A selected_component whose selector_name can denote the (implicit) overriding
of an inherited primitive of a synchronized type, as well as denote an entry
(or protected subprogram) that implements the inherited primitive, is not
ambiguous, and resolves to the entry (or protected subprogram).
!question
Consider the following example:
package Synch_Pkg is
type Synch_Interface is synchronized interface;
procedure Prim (S : in out Synch_Interface) is abstract;
procedure Yet_Another_Op (Obj : in out Synch_Interface'Class);
end Synch_Pkg;
with Synch_Pkg;
package Task_Pkg is
task type Task_Type is new Synch_Pkg.Synch_Interface with
entry Prim;
entry Other_Prim;
entry Yet_Another_Op;
end Task_Type;
--
--
procedure Other_Prim (Tsk : in out Task_Type); --
end Task_Pkg;
...
T : Task_Pkg.Task_Type;
...
T.Prim; --
T.Other_Prim; --
declaration is illegal.)
T.Yet_Another_Op; --
The call to Prim at (1) using prefixed notation appears to be ambiguous,
because the selector could denote either the entry Prim, or the implicitly
declared overriding of the primitive inherited from Synch_Interface (which
is defined to exist by AI05-0042). This is clearly not what is intended.
Also, there can be subprograms with prefixed views that are homographic
with an entry of the task type, such as procedures Yet_Another_Op and
Other_Prim, but that means that calls using prefixed notation are
ambiguous, because the call could be either to the subprogram or to the
entry (by 4.1.3 paragraphs 8-9.2/2). Are such calls intended to be
ambiguous? (Yes, but in the case of Other_Prim the procedure declaration
is already illegal by 9.1(9.5/2).)
!recommendation
(See summary.)
!wording
Modify 4.1.3(9.2/2):
The prefix (after any implicit dereference) shall resolve to denote an
object or value of a specific tagged type T or class-wide type T'Class.
The selector_name shall resolve to denote a view of a subprogram declared
immediately within the declarative region in which an ancestor of the type
T is declared. The first formal parameter of the subprogram shall be of
type T, or a class-wide type that covers T, or an access parameter
designating one of these types. The designator of the subprogram shall not
be the same as that of a component of the tagged type visible at the point
of the selected_component. {The subprogram shall not be an implicitly
declared primitive operation of type T that overrides an inherited subprogram
implemented by an entry or protected subprogram visible at the point of
the selected_component.} The selected_component denotes a view of this
subprogram that omits the first formal parameter. This view is called
a prefixed view of the subprogram, and the prefix of the selected_component
(after any implicit dereference) is called the prefix of the prefixed view.
Add this AARM paragraph following 4.1.3(9.2/2):
AARM Discussion: The part of the rule that excludes a primitive overriding
subprogram as a selector applies only to the wrapper subprogram that is
implicitly declared to override a subprogram inherited from a synchronized
interface that is implemented by an operation of a task or protected type
(see 9.1 and 9.4, as amended by AI05-0042). We don't want
calls that use a prefixed view to be ambiguous between the wrapper
subprogram and the implementing entry or protected operation. Note that
it is illegal to declare an explicit primitive that has a prefixed view
that is homographic with one of the type's operations, so
in normal cases it isn't possible to have an ambiguity in a prefix call.
However, a class-wide operation of an ancestor type and declared in the
same declarative list with the ancestor type is also considered, and that
can make a call ambiguous.
Replace 9.1(9.5/2):
The prefixed view profile of an explicitly declared primitive subprogram
of a tagged task type shall not be type conformant with any entry of the
task type, if the first parameter of the subprogram is of the task type
or is an access parameter designating the task type.
with the following:
The prefixed view profile of an explicitly declared primitive subprogram
of a tagged task type shall not be type conformant with any entry of the
task type, if the subprogram has the same defining name as the entry
and the first parameter of the subprogram is of the task type or is
an access parameter designating the task type.
Replace 9.4(11.4/2):
The prefixed view profile of an explicitly declared primitive subprogram
of a tagged protected type shall not be type conformant with any protected
operation of the protected type, if the first parameter of the subprogram
is of the protected type or is an access parameter designating the protected
type.
with the following:
The prefixed view profile of an explicitly declared primitive subprogram
of a tagged protected type shall not be type conformant with any protected
operation of the protected type, if the subprogram has the same
defining name as the protected operation and the first parameter of the
subprogram is of the protected type or is an access parameter designating
the protected type.
!discussion
The ambiguity in the case of the call at (3), to a synchronized operation
declared within a task or protected type that is a homograph of the prefixed
view of an explicit subprogram, seems unavoidable. We could try to define
some preference rule similar to that for components that conflict with
prefixed views, as is done in 4.1.3(9.2/2), to select the entry or protected
subprogram interpretation, but that seems like a bad idea.
For one thing, unlike a component, such operations are overloadable.
Giving preference to either the synchronized operation or the subprogram
with the homographic prefixed view could too easily result in confusion
as to which operation was being named. So it's best to leave the language
as it is, with the potential for ambiguities, but ones that can generally
be avoided either using normal function call notation rather than a
prefixed view, or by using named notation on calls.
In the case of the entry and primitive procedure named Other_Prim in the
question, the declaration of the procedure is illegal by the existing rule
in 9.1(9.5/2), which disallows explicitly declared primitives that have a
prefixed view that is homographic with an entry of the type. (A similar rule
exists in 9.4(11.4/2), covering the case of protected operations.) One
oversight that was noted, though, is that those rules need to mention that
the conflicting subprogram must have the same defining_identifier (or
defining_operator_symbol) as the entry or protected subprogram, so those
paragraphs are corrected to reflect that.
The first part of the question (concerning the call at (1)) involves a
similar case, but one where we definitely want the call to resolve to one
of the two available interpretations, since otherwise prefixed notation
can't be used at all.
The situation is that of a subprogram inherited from a synchronized
interface that is implemented by an entry or protected subprogram.
By AI05-0042, such an inherited subprogram is defined to be overridden
by an implicit subprogram (see the last sentence of 9.1(9.2/3) and
9.4(11.1/3)). The problem is that a call to the implicitly declared
overriding subprogram using prefixed notation will be ambiguous,
because it could also be interpreted as a call to the entry or protected
subprogram that implements the inherited subprogram. In some cases
such a call could be disambiguated using named associations for the
parameters, but having to use parameter names to disambiguate calls
would only be an ugly workaround and an inconvenience for users.
Clearly a change is needed to effectively give preference to one of
the two operations. This is accomplished by choosing the entry
(or protected subprogram), and removing the interpretation of the
implicit overriding operation at the point of a selector_name in
a prefixed context. It makes sense to resolve in favor of the entry
or protected subprogram over the implicit overriding subprogram since
the former is explicit in the program text. This preference rule,
added to 4.1.3(9.2/2), is similar to the rule in that same paragraph
for preferring a component over a subprogram with the same name.
!corrigendum 4.1.3(9.2/2)
Replace the paragraph:
The prefix (after any implicit dereference) shall resolve to
denote an object or value of a specific tagged type T or class-wide type
T'Class. The selector_name shall resolve to denote a view of a
subprogram declared immediately within the declarative region in which an
ancestor of the type T is declared. The first formal parameter of the
subprogram shall be of type T, or a class-wide type that covers T, or
an access parameter designating one of these types. The designator of the
subprogram shall not be the same as that of a component of the tagged type
visible at the point of the selected_component. The
selected_component denotes a view of this subprogram that omits the first
formal parameter. This view is called a prefixed view of the subprogram,
and the prefix of the selected_component (after any implicit
dereference) is called the prefix of the prefixed view.
by:
The prefix (after any implicit dereference) shall resolve to
denote an object or value of a specific tagged type T or class-wide type
T'Class. The selector_name shall resolve to denote a view of a
subprogram declared immediately within the declarative region in which an
ancestor of the type T is declared. The first formal parameter of the
subprogram shall be of type T, or a class-wide type that covers T, or
an access parameter designating one of these types. The designator of the
subprogram shall not be the same as that of a component of the tagged type
visible at the point of the selected_component. The subprogram shall not
be an implicitly declared primitive operation of type T that overrides
an inherited subprogram implemented by an entry or protected subprogram
visible at the point of the selected_component. The
selected_component denotes a view of this subprogram that omits the first
formal parameter. This view is called a prefixed view of the subprogram,
and the prefix of the selected_component (after any implicit
dereference) is called the prefix of the prefixed view.
!corrigendum 9.1(9.5/2)
Replace the paragraph:
The prefixed view profile of an explicitly declared primitive subprogram
of a tagged task type shall not be type conformant with any entry of the
task type, if the first parameter of the subprogram is of the task type
or is an access parameter designating the task type.
by:
The prefixed view profile of an explicitly declared primitive subprogram
of a tagged task type shall not be type conformant with any entry of the
task type, if the subprogram has the same defining name as the entry
and the first parameter of the subprogram is of the task type or is
an access parameter designating the task type.
!corrigendum 9.4(11.4/2)
Replace the paragraph:
The prefixed view profile of an explicitly declared primitive subprogram
of a tagged protected type shall not be type conformant with any protected
operation of the protected type, if the first parameter of the subprogram
is of the protected type or is an access parameter designating the protected
type.
by:
The prefixed view profile of an explicitly declared primitive subprogram
of a tagged protected type shall not be type conformant with any protected
operation of the protected type, if the subprogram has the same
defining name as the protected operation and the first parameter of the
subprogram is of the protected type or is an access parameter designating
the protected type.
!ACATS Test
An ACATS C-Test should be written to check that the legal case in the
example actually works.
!appendix
From: Gary Dismukes
Sent: Monday, February 4, 2008 4:44 PM
This is the draft version of the AI assigned to me in Fairfax (not assigned
a number yet) [this is version /01 of the AI - ED],
which arose out of a question raised during the meeting.
There are actually two similar questions involving apparent ambiguities
that can occur with prefixed calls to operations of synchronized tagged
types considered here. One of these cases of ambiguities doesn't seem
to require any action, but the other one needs correction. The most
appropriate way to fix this can be discussed at the upcoming meeting
(assuming this makes it to the agenda), but in this draft I've suggested
one way that it could be fixed.
****************************************************************
From: Edmond Schonberg
Sent: Monday, February 4, 2008 5:08 PM
...
> procedure Prim (S : Synch_Interface) is abstract;
S should be an in-out parameter if it is to be implemented by an entry.
...
> The call to Prim at (1) using prefixed notation appears to be ambiguous,
> because the selector could denote either the entry Prim, or the implicitly
> declared overriding of the primitive inherited from Synch_Interface (which
> is defined to exist by AI05-0042). This is clearly not what is
> intended.
Agreed.
> [Or perhaps the preference should really be the other way around, with
> the implicit overriding subprogram being hidden from all visibility in
> a prefixed call:
>
> The declaration of an entry or protected subprogram that implements
> a subprogram inherited from a progenitor type is hidden from all
> visibility at the point of a selector_name in a selected_component
> whose prefix resolves to an object or value of the parent task or
> protected type.
But in that case the second declaration would be legal, because the
implicit subprogram would then be overridden by the explicit one
according to the usual rules, and there would be no ambiguity. So
the first choice is preferable (if we want (2) to remain ambiguous.
****************************************************************
From: Gary Dismukes
Sent: Monday, February 4, 2008 6:35 PM
...
> > procedure Prim (S : Synch_Interface) is abstract;
>
> S should be an in-out parameter if it is to be implemented by an entry.
You're right, thanks for catching. I missed going back and making that
correction despite having corrected my compilation test of the same code.
[Correction made in version /01 of the AI - ED.]
> > [Or perhaps the preference should really be the other way around, with
> > the implicit overriding subprogram being hidden from all visibility in
> > a prefixed call:
(Aargh, I just noticed that I failed to adjust the wording on the above
paragraph after swapping some of my text around. That one should read
"with the entry or protected subprogram being hidden...". That's what
I get for running out of time and not doing a final careful review of
what I'd written. At least the next paragraph reflected what I meant
in the above.) [Correction made in version /01 of the AI - ED.]
> > The declaration of an entry or protected subprogram that implements
> > a subprogram inherited from a progenitor type is hidden from all
> > visibility at the point of a selector_name in a selected_component
> > whose prefix resolves to an object or value of the parent task or
> > protected type.
>
> But in that case the second declaration would be legal, because the
(I assume you mean "the second call" above rather than "second declaration".)
> implicit subprogram would then be overridden by the explicit one
> according to the usual rules, and there would be no ambiguity. So
> the first choice is preferable (if we want (2) to remain ambiguous.
I think there are two confusions here. First, the operation
Other_Prim called at (2) isn't a case of overriding, as there's
no inherited operation by that name in my example. But second,
if it were an overriding, then there would be a violation of the
rules in 9.1(9.6/2-9.8/2), which disallow having both an overriding
primitive and an "implemented by" operation for an inherited subprogram.
So I don't think that the fix for (1) would have any effect on the
ambiguity of cases such as (2).
****************************************************************
From: Edmond Schonberg
Sent: Monday, February 4, 2008 10:27 PM
> I think there are two confusions here. First, the operation
> Other_Prim called at (2) isn't a case of overriding, as there's
> no inherited operation by that name in my example. But second,
> if it were an overriding, then there would be a violation of the
> rules in 9.1(9.6/2-9.8/2), which disallow having both an overriding
> primitive and an "implemented by" operation for an inherited
> subprogram.
> So I don't think that the fix for (1) would have any effect on the
> ambiguity of cases such as (2).
Right, I misread the example, Other_Prim is well-named, and this is
definitely (unambiguously?) ambiguous.
****************************************************************
From: Tucker Taft
Sent: Monday, February 4, 2008 8:21 PM
> ... Another possibility would be
> to try and make certain declarations illegal, but that isn't appealing
> either, as it would introduce illegalities for no particularly good
> reason (plus it wouldn't work for technical reasons).
Can you explain these "technical reasons"?
We make it illegal to have an entry or
protected subprogram that is homographic with the
prefixed view of an explicit overriding. Why can't we
do the same for an explicit non-overriding primitive?
> ...
> Clearly we need a change to effectively give preference to one of the
> two operations. The proposed fix is to prefer the interpretation of
> the entry (or protected subprogram), and to consider the implicit
> overriding operation effectively hidden at the point of a selector_name
> in a prefixed call. It seems somewhat more natural to prefer the entry
> or protected subprogram over the implicit overriding subprogram since
> the former is explicit in the program text (though formulating the
> rule the other way could also be considered).
I strongly prefer having the entry/protected subprogram
visible via prefixed notation. That is what you would
get in the absence of the interface, and it seems weird
that the formal parameter names, defaults, etc., would
suddenly change just because the task type now implements
an interface. So I agree with your current solution, and
would be opposed to the alternate you considered.
> ...In terms of the rules,
> this is implemented by making the implicit overriding subprogram
> hidden from all visibility at the point of a selector_name in cases
> that would otherwise be ambiguous.
Do we really need to use the term "hidden from all visibility" here?
I think all you need to do is have 4.1.3(9.2) include a rule
that disallows referring to a primitive subprogram that is implemented
by an entry or protected subprogram. Remember that 4.1.3(9.2)
is all considered "Name Resolution" so disallowing something is
effectively creating an overload resolution rule. Hiding from
"all visibility" seems like overkill, and is probably exactly
what we *don't* want to do, since we still want to be able to
refer to the implicitly declared primitive using "unprefixed"
subprogram call notation.
****************************************************************
From: Gary Dismukes
Sent: Wednesday, February 6, 2008 12:11 AM
> > ... Another possibility would be
> > to try and make certain declarations illegal, but that isn't appealing
> > either, as it would introduce illegalities for no particularly good
> > reason (plus it wouldn't work for technical reasons).
>
> Can you explain these "technical reasons"?
> We make it illegal to have an entry or
> protected subprogram that is homographic with the
> prefixed view of an explicit overriding. Why can't we
> do the same for an explicit non-overriding primitive?
You're right, we could do that, and I started off by doing that.
But there are other cases that that have a similar effect where
the conflicting operation isn't a primitive, such as a class-wide
subprogram:
procedure Other_Op (T : Synchronized_Type'Class);
Do we want to disallow that as well? I'm assuming we don't.
At the time it had seemed to me to be needlessly restrictive to
disallow any of these cases. After all, an implementation can
always issue a warning that certain calls will be ambiguous. I was
thinking that a user might have some reason to declare an explicit
primitive that conflicts, and have a homographic task entry that
can still be called from within the task even though it can't be
called from outside. But I'm willing to admit that that's a stretch,
and probably isn't an idiom worth allowing, so if the feeling is that
such a conflict with a primitive almost certainly indicates an error,
then I'm willing to go along with making the case of a primitive
illegal.
> > ...
> > Clearly we need a change to effectively give preference to one of the
> > two operations. The proposed fix is to prefer the interpretation of
> > the entry (or protected subprogram), and to consider the implicit
> > overriding operation effectively hidden at the point of a selector_name
> > in a prefixed call. It seems somewhat more natural to prefer the entry
> > or protected subprogram over the implicit overriding subprogram since
> > the former is explicit in the program text (though formulating the
> > rule the other way could also be considered).
>
> I strongly prefer having the entry/protected subprogram
> visible via prefixed notation. That is what you would
> get in the absence of the interface, and it seems weird
> that the formal parameter names, defaults, etc., would
> suddenly change just because the task type now implements
> an interface. So I agree with your current solution, and
> would be opposed to the alternate you considered.
For some reason I was wavering, then ended up leaning towards
the recommended preference, but hadn't fully solidified my commitment
to that by the time I wrote it up, even though it felt right to me
based on wanting to get the formal names, etc. However, your comment
has convinced me that it's the right choice. :-) (I was a little
worried that some semantic glitch might pop up that would argue for
preferring the other, so wanted to leave the option open, but that was
most probably just FUD.)
> > ...In terms of the rules,
> > this is implemented by making the implicit overriding subprogram
> > hidden from all visibility at the point of a selector_name in cases
> > that would otherwise be ambiguous.
>
> Do we really need to use the term "hidden from all visibility" here?
> I think all you need to do is have 4.1.3(9.2) include a rule
> that disallows referring to a primitive subprogram that is implemented
> by an entry or protected subprogram. Remember that 4.1.3(9.2)
> is all considered "Name Resolution" so disallowing something is
> effectively creating an overload resolution rule. Hiding from
> "all visibility" seems like overkill, and is probably exactly
> what we *don't* want to do, since we still want to be able to
> refer to the implicitly declared primitive using "unprefixed"
> subprogram call notation.
I defined it as hidden only within the specific context of the
selector_name, not hidden in general, so that it wouldn't affect
normal calls, but I admit that's an unorthodox use of "hidden from
all visibility". Anyway, I'm fine with going the route of adding
a rule in 4.1.3 to cover this case, and will try to draft some
wording for that.
BTW, in your comment above you say "disallows referring to a primitive
subprogram that is implemented by...", but is that really what we
want? That would disallow dispatching calls using prefixed notation.
My attempted fix was written to hide the implicit primitive only for
calls that could be made to the entry itself, that is, calls where
the prefix is of the specific type, but to still allow calls with
class-wide prefixes to be made to the dispatching primitive.
It seems unfortunate to lose the dispatching calls, though obviously
those would still be possible using normal call notation, just not with
prefixed notation. Wouldn't it be preferable to try and formulate the
rule so as to also permit dispatching calls that use prefixed notation?
****************************************************************
From: Tucker Taft
Sent: Wednesday, February 6, 2008 5:30 AM
> You're right, we could do that, and I started off by doing that.
> But there are other cases that that have a similar effect where
> the conflicting operation isn't a primitive, such as a class-wide
> subprogram:
>
> procedure Other_Op (T : Synchronized_Type'Class);
>
> Do we want to disallow that as well? I'm assuming we don't.
These aren't homographs, so trying to make these illegal
is probably more trouble than it is worth. But that doesn't
change my mind about disallowing the more common case of
a homographic primitive.
>
> At the time it had seemed to me to be needlessly restrictive to
> disallow any of these cases. After all, an implementation can
> always issue a warning that certain calls will be ambiguous. I was
> thinking that a user might have some reason to declare an explicit
> primitive that conflicts, and have a homographic task entry that
> can still be called from within the task even though it can't be
> called from outside. But I'm willing to admit that that's a stretch,
> and probably isn't an idiom worth allowing, so if the feeling is that
> such a conflict with a primitive almost certainly indicates an error,
> then I'm willing to go along with making the case of a primitive
> illegal.
I think that is more consistent. It seems weird that it is illegal
to have a homographic overriding, but it is OK to have a homographic
operation that does *not* override an inherited primitive. I don't
think you are doing the user any favors by having this distinction.
...
> It seems unfortunate to lose the dispatching calls, though obviously
> those would still be possible using normal call notation, just not with
> prefixed notation. Wouldn't it be preferable to try and formulate the
> rule so as to also permit dispatching calls that use prefixed notation?
I'm not sure what you mean by "losing" dispatching calls.
If I have a prefix of task_type'Class, I still have visibility
on the entries of task_type I hope! I just don't need to
do any "dispatching" to know which entry, since you can't
further extend a concrete task type. This is similar to referring
to the components of a record type when the prefix of the
selected component is record_type'Class. No dispatching is
involved.
****************************************************************
From: Randy Brukardt
Sent: Saturday, June 14, 2008 12:37 AM
...
> Consider the following example:
>
> package Synch_Pkg is
>
> type Synch_Interface is synchronized interface;
>
> procedure Prim (S : in out Synch_Interface) is abstract;
>
> task type Task_Type is new Synch_Interface with
> entry Prim;
> entry Other_Prim;
> entry Yet_Another_Op;
> end Task_Type;
>
> package Nested_Pkg is
> procedure Yet_Another_Op (Tsk : in out Task_Type);
> end Nested_Pkg;
>
> -- Implicit declaration of overriding primitive (as per AI05-0042):
> -- procedure Prim (S : in out Task_Type);
>
> procedure Other_Prim (Tsk : in out Task_Type); -- Legal? (No.)
>
> end Synch_Pkg;
>
> ...
>
> T : Synch_Pkg.Task_Type;
>
> use Synch_Pkg.Nested_Pkg;
...
> T.Yet_Another_Op; -- (2) Ambiguous? (Yes.)
I don't understand this. The operation in the nested package is not eligible
to be a prefixed view, as it is not "declared *immediately* within the
declarative region where an ancestor of T is declared". The use clause is
irrelevant, that would make the operation directly visible as:
Yet_Another_Op(T);
but that's not relevant here.
I think the only way to get an ambiguity is with a class-wide operation (which
could be in an ancestor package):
procedure Yet_Another_Op (Obj : in out Synch_Interface'Class);
Thus, the example of the question would probably be better written as:
package Synch_Pkg is
type Synch_Interface is synchronized interface;
procedure Prim (S : in out Synch_Interface) is abstract;
procedure Yet_Another_Op (Obj : in out Synch_Inteface'Class);
end Synch_Pkg;
with Synch_Pkg;
package Task_Pkg is
task type Task_Type is new Synch_Pkg.Synch_Interface with
entry Prim;
entry Other_Prim;
entry Yet_Another_Op;
end Task_Type;
-- Implicit declaration of overriding primitive (as per AI05-0042):
-- procedure Prim (S : in out Task_Type);
procedure Other_Prim (Tsk : in out Task_Type); -- Legal? (No.)
end Task_Pkg;
...
T : Task_Pkg.Task_Type;
...
T.Prim; -- (1) Ambiguous? (No.)
T.Other_Prim; -- (2) Ambiguous? (Not possible; the procedure
declaration is illegal.)
T.Yet_Another_Op; -- (2) Ambiguous? (Yes.)
****************************************************************
From: Gary Dismukes
Sent: Saturday, June 14, 2008 12:57 AM
> I don't understand this. The operation in the nested package is not
> eligible to be a prefixed view, as it is not "declared *immediately*
> within the declarative region where an ancestor of T is declared". The
> use clause is irrelevant, that would make the operation directly visible as:
> Yet_Another_Op(T);
> but that's not relevant here.
You're right. I was trying to illustrate a case like 2) that showed a
legitimate ambiguity (since the call 2) turned out to be wrong because
of the illegality) and ended up screwing up the example.
> I think the only way to get an ambiguity is with a class-wide
> operation (which could be in an ancestor package):
Yes, that would make more sense. Thanks for the correction.
I guess I'll be seeing this AI again...
****************************************************************
From: Randy Brukardt
Sent: Saturday, June 14, 2008 1:57 AM
...
> > I think the only way to get an ambiguity is with a class-wide
> > operation (which could be in an ancestor package):
>
> Yes, that would make more sense. Thanks for the correction.
I just noticed that there are two calls labeled (2) in the question.
I'll replace the example with mine and fix the calls to have different numbers.
> I guess I'll be seeing this AI again...
Maybe, but not for this reason. But I'm didn't check the discussion very closely.
****************************************************************
Questions? Ask the ACAA Technical Agent