JDK-6795689 : javac can produce type-unsafe programs without any warning
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6u10
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2009-01-20
  • Updated: 2010-04-26
  • Resolved: 2009-01-20
Related Reports
Duplicate :  
Description
J2SE Version (please include all output from java -version flag):
java version "1.6.0_10"


Does this problem occur on J2SE 1.3, 1.4.x or 1.5?  Yes / No (pick one)
Not tested, however 1.6.0_02 and 1.6.0_04 produce the same problem.


Operating System Configuration Information (be specific):
Windows Server 2003 SP 2


Hardware Configuration Information (be specific):
Toshiba Tecra S5


Bug Description:
javac can produce type-unsafe programs without any warning.

Example:

class Test
{
    static abstract class Fn<A, B>
    {
        public abstract B applyTo(A value);

        public <X> Fn<X, B> after(final Fn<? super X, ? extends A> fn)
        {
            return new Fn<X, B>()
            {
                public B applyTo(X value)
                {
                    A intermediate = fn.applyTo(value);
                    return Fn.this.applyTo(intermediate);
                }
            };
        }
    }

    static final Fn<Object, String> TO_STRING = new Fn<Object, String>()
    {
        public String applyTo(Object obj) { return obj.toString(); }
    };

    static final Fn<Boolean, Boolean> COMPLEMENT = new Fn<Boolean, Boolean>()
    {
        public Boolean applyTo(Boolean b) { return !b; }
    };

    public static void main(String[] args)
    {
        // The following assignment shouldn't compile!
        Fn<Object, String> f = TO_STRING.after(COMPLEMENT);
        // Invocations of f.applyTo() then cause a ClassCastException:
        System.out.println(f.applyTo(new Object()));
    }
}


Observation:
 
The compiler allows invocations of after() for any X, without verifying that X is actually a subtype of the type argument A of fn's type, as required by '? super X'. As a consequence, the resulting program can be type-unsafe without any warning.

Comments
EVALUATION This is a duplicate of 6638712 - here's a simplified test case: class Foo<A, B> { <X> Foo<X, B> m(Foo<? super X, ? extends A> foo) { return null;} } class Test { void test(Foo<Object, String> foo) { Foo<Object, String> foo2 = foo.m((Foo<Boolean, Boolean>)null); } } Which shouldn't compile because X is inferred to be Object during 15.12.2.8 - X = Object makes the method inapplicable, because Foo<Boolean, Boolean> cannot be passed where [X=Object, A:=Object, B:=String]Foo<? super X, ? extends A> = Foo<? super Object, ? extends Object>, because Boolean is not contained by ? super Object.
20-01-2009