JDK-6558559 : Extra "unchecked" diagnostic
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 5.0
  • Priority: P5
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2007-05-17
  • Updated: 2012-01-13
  • Resolved: 2012-01-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b44Fixed
Related Reports
Relates :  
Description
The following deserves no unchecked diagnostic, but javac produces one anyway.

interface A<T> {}
class B<T> {}

class C {
        A<?> x = null;
        B y = (B)x;
}
Another test case reported by the Eclipse team

import java.util.*;
public class X {
    X(List rawList, List<?> unboundList) {
            Throwable t0 = (Throwable) Collections.emptyList(); // unchecked
            Throwable t1 = (Throwable) rawList; // no warn
            Throwable t2 = (Throwable) unboundList; // unchecked
            Object o = unboundList;
            Throwable t3 = (Throwable) o; // no warn
    }
}
Another test case clearly showing the silliness of the warning:

public class C {
    interface I<T> {}
    static void m(I<?> o) {
        System.out.println("checking " + o);
        System.out.println("[#1] instance of Exception? " + (o instanceof Exception));
        System.out.println("[#2] instance of Exception? " + Exception.class.isInstance(o));
        System.out.println("[#3] instance of Exception? " + ((I) o instanceof Exception));
    }
    public static void main(String[] x) {
        class I1 implements I<String> {}
        m(new I1());
        class I2 extends Exception implements I<String> {}
        m(new I2());
    }
}

Though all three checks do the same thing, line #1 elicits an unchecked warning from the compiler. Note that checking 'o instanceof Cloneable' (an interface) results in no warning.

Comments
SUGGESTED FIX A webrev of this fix is available at the following URL: http://hg.openjdk.java.net/jdk7/tl/langtools/rev/e157bd68dfc5
13-01-2009

EVALUATION The fix solves also the 3rd problem reported in 'description'; I'll add another regression test.
05-12-2008

EVALUATION It was indeed a bug in Types.sideCast; javac sometimes finds it useful to swap source type S with target type T - however it should keep track of this swap in order to emit unchecked warnings accordingly. While this is done in most circumstances, I discovered that this wasn't the case in side case impl. As a result javac thought that the target type was S (A<#> in the first example, List<Object> in the second example) thus triggering the warning. Adjusting the implementation fixes both problems.
02-12-2008

EVALUATION In both cases we have a cast from an interface to a class type, so (accordingly to JLS 5.5) : "if S is an interface type: * If T is an array type, then T must implement S, or a compile-time error occurs. * If T is a type that is not final (��8.1.1), then if there exists a supertype X of T, and a supertype Y of S, such that both X and Y are provably distinct parameterized types, and that the erasures of X and Y are the same, a compile-time error occurs. Otherwise, the cast is always legal at compile time (because even if T does not implement S, a subclass of T might).* * If T is a type that is final, then: o If S is not a parameterized type or a raw type, then T must implement S, and the cast is statically known to be correct, or a compile-time error occurs. o Otherwise, S is either a parameterized type that is an invocation of some generic type declaration G, or a raw type corresponding to a generic type declaration G. Then there must exist a supertype X of T, such that X is an invocation of G, or a compile-time error occurs. Furthermore, if S and X are provably distinct parameterized types then a compile-time error occurs. " We should apply 2nd bullet here (T is a non-final type in both cases). However I don't see how this might trigger an unchecked warning. Moreover, reading from the beginning of 5.5, we infer that an unchecked cast might be triggered in the following cases: "A cast from a type S to a parameterized type (��4.5) T is unchecked unless at least one of the following conditions hold: * S <: T. * All of the type arguments (��4.5.1) of T are unbounded wildcards. * T <: S and S has no subtype XT , such that the erasures (��4.6) of X and T are the same. " Which means that T should be parameterized (not true in both examples) for the warning to be raised. It looks like a bug in the side cats implementation.
02-12-2008