Possible Bug in javac unchecked cast detection
Alex Buckley
alex.buckley at oracle.com
Fri May 2 19:55:29 UTC 2014
If none of the interface declarations were generic, then the language
would happily accept the cast from SubInterfaceA to SubInterfaceB; as
JLS 5.5.1 says, "the cast is always legal at compile time (because even
if T does not implement S, a subclass of T might)."
With generic declarations, the unchecked cast rules come into play,
aiming to warn you if anything happens that could possibly lead to a
ClassCastException at run time. These rules could have been smarter, to
detect the common superinterface of SubInterfaceA<String> and
SubInterfaceB<String>, but that decision was not taken in 1998.
Alex
On 5/2/2014 1:12 AM, Tom Schindl wrote:
> Hi Alex,
>
> Thanks for the confirmation. I'll file a bug against javac then. What I
> don't yet understand how one can fix such a situation without a warning
> or why JLS does not allow the cast.
>
> I can fix the unchecked warning with but then (if turned on in my
> Eclipse I get a warning about an unnecessary typecast - so do IntelliJ
> users)
>
> b = (SubInterfaceB<String>)(BaseInterface<String>)a;
>
> which of course is correct because one does not need to cast
> SubInterfaceA<T> to BaseInterface<T>. The only solution to work without
> any warning suppression is using an intermediate variable.
>
> BaseInterface<T> temp = a;
> b = (SubInterfaceB<String>)temp;
>
> what i don't fully grasp then why JLS does not directly allow me to cast
> from SubInterfaceA<T> to SubInterfaceB<T>.
>
> Tom
>
> On 01.05.14 20:41, Alex Buckley wrote:
>> Eclipse is right. Given the interface declarations below, a cast from
>> SubInterfaceA<String> to SubInterfaceB<String> is unchecked. By JLS
>> 5.5.2, an unchecked warning is due unless @SuppressWarnings is in
>> effect; lint mode doesn't matter.
>>
>> Alex
>>
>> On 5/1/2014 9:11 AM, Tom Schindl wrote:
>>> Hi,
>>>
>>> While cleaning up the javafx codebase (who has a lot of use of generics)
>>> I came across casts the eclipse java compiler marks as unchecked while
>>> javac -Xlint:all does not warn about.
>>>
>>> The following snippet shows gist of the problem:
>>>
>>>> package a;
>>>>
>>>> public class CastTest {
>>>> public interface BaseInterface<T> {
>>>>
>>>> }
>>>>
>>>> public interface SubInterfaceA<T> extends BaseInterface<T> {
>>>>
>>>> }
>>>>
>>>> public interface SubInterfaceB<T> extends BaseInterface<T> {
>>>>
>>>> }
>>>>
>>>> public static void main(String[] args) {
>>>> SubInterfaceA<String> a = null;
>>>> SubInterfaceB<String> b = (SubInterfaceB<String>) a; // javac
>>>> does not warn
>>>> b = (SubInterfaceB<String>)(BaseInterface<String>)a;
>>>>
>>>> }
>>>> }
>>>
>>> I first thought of a bug in the eclipse compiler but they claim their
>>> compiler is correct because the spec says:
>>>
>>>
>>>> "A cast from a type S to a parameterized type (§4.5) T is unchecked
>>>> unless at least one of the following is true:
>>>> * S <: T
>>>> * All of the type arguments (§4.5.1) of T are unbounded wildcards
>>>> * T <: S and S has no subtype X other than T where the type
>>>> arguments
>>>> of X are not contained in the type arguments of T."
>>>
>>> So before fileing a bug and start fixing the javafx code I wanted to get
>>> feedback from the compiler gurus on this list who is right and who is
>>> wrong.
>>>
>>> Thanks
>>>
>>> Tom
>>>
>
More information about the compiler-dev
mailing list