Unchecked conversion and super raw type
Alex Buckley
alex.buckley at oracle.com
Fri Aug 23 15:46:25 PDT 2013
On second thoughts, this is a complicated mess.
foo(B) is applicable by subtyping and foo(A<String>) isn't. Since at
least one method is applicable by subtyping, overload resolution should
stop and foo(B) should be selected.
If overload resolution was to proceed to applicability by method
invocation conversion, it would find that foo(A<String>) is applicable
(as described earlier) and also that foo(B) is applicable (identity
conversion) - but it's not meant to proceed!
So, javac is wrong to give an ambiguity. Or is it? In the pre-generics
world - static class A {} ... void foo(A a) ... - JLS2 would have said
that "foo(b)" was ambiguous because foo(A) and foo(B) were both
applicable by method invocation conversion. Generifying the declaration
of class A and parameterizing the formal parameter type A should not
change that. And so, JLS3's two-stage applicability testing is
inaccurate when it chooses foo(B) as The Answer.
Perhaps if I had a complete description of javac's overload resolution
rules, I could make 15.12.2 reflect what really happens. Or maybe this
whole idea of "migration compatibility" is just too hard.
Alex
On 8/23/2013 3:18 PM, Alex Buckley wrote:
> I am happy to report that JLS7 makes foo(A<String>) applicable by method
> invocation conversion (15.12.2.3), so javac is right to report an
> ambiguity.
>
> Method invocation conversion allows B to undergo a widening reference
> conversion to A, because B's direct supertype is A; and then, because A
> is a raw type, an unchecked conversion may be applied from A to A<String>.
>
> Alex
>
> On 4/12/2013 3:25 AM, Maurizio Cimadamore wrote:
>> The spec is saying:
>>
>> "The method m is applicable by subtyping if and only if both of the
>> following conditions hold:
>>
>> For 1 ≤ i ≤ n, either:
>>
>> Ai <: Si (§4.10), or
>>
>> Ai is convertible to some type Ci by unchecked conversion (§5.1.9), and
>> Ci <: Si."
>>
>>
>> And I agree this seems to be a spec problem - there's no unchecked
>> conversion for going from B to A<String>, as unchecked conversion
>> requires that source bases type and target nbae type are the same - in
>> this case we have that B != A so no unchecked conversion applies.
>>
>> However, javac (and Eclipse) implement a relaxed check; for example,
>> javac is happy whenever it can find a supertype of the LHS type that
>> matches the base type of the RHS. Which in this case is satisfied.
>>
>> Maurizio
>>
>>
>> On 11/04/13 23:40, Zhong Yu wrote:
>>>
>>>
>>>
>>> On Thu, Apr 11, 2013 at 5:10 PM, Zhong Yu <zhong.j.yu at gmail.com
>>> <mailto:zhong.j.yu at gmail.com>> wrote:
>>>
>>> Consider this example:
>>>
>>> public class Test
>>> {
>>> static class A<T> {}
>>>
>>> static class B extends A {}
>>>
>>> void foo(A<String> a) {}
>>>
>>> void foo(B b) {}
>>>
>>> void test()
>>> {
>>> B b = new B();
>>> foo(b); // error: reference to foo is ambiguous
>>> }
>>> }
>>>
>>> For the method invocation expression `foo(b)`, method `foo(B)` is
>>> applicable by subtyping. However is that also true for
>>> `foo(A<String>)`? By the letter of the spec, we cannot find a Ci
>>> such that "B" is convertible to Ci by unchecked conversion and Ci
>>> <: A<String>. So my understanding is that `foo(A<String>)` is not
>>> applicable to `foo(b)` by subtyping, and the code should compile
>>> since only one applicable method is found during "15.12.2.2.
>>> Phase 1"
>>>
>>>
>>>
>>> Or, is this a bug of the spec? Maybe the spec intends to say
>>>
>>> For 1 ≤ /i/ ≤ /n/, either:
>>>
>>> *
>>>
>>> A_i |<:| S_i (§4.10
>>>
>>> <http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.10>),
>>> or
>>>
>>> *
>>>
>>> A_i |<:| |S_i |
>>>
>>> The second clause is for the legacy code that saw a non-generic method
>>> parameter type.
>>>
>>> Zhong Yu
>>>
>>
More information about the compiler-dev
mailing list