Search code examples
javajava-8typechecking

Type checking broken on matching capture with upper bound?


Create a class like

public class Play {
    public static void main(String[] args) throws Exception {
        outer(Integer.class, inner("abc"));
    }

    static <C> void outer(Class<C> c, List<? super C> s){
    }

    static <C> List<C> inner(C c) {
        return null;
    }
}

and it compiles in Java 8! (Both in Eclipse 4.5 and JDK1.8_25) https://ideone.com/Q9JLHP

In Eclipse, all the bounds are inferred correctly, but how could outer's capture Supplier<? super Integer> ever been satisfied by the argument Supplier<String>??

Edit: clarified this is Java 8-specific and made the example less confusing.


Solution

  • inner("abc") can, at the compiler's discretion, be interpreted as a Supplier of any supertype of String. -- for example,

    Supplier<Object> inner = inner("abc");
    

    works just fine, because "abc" is also an Object. That's what's happening here: inner is returning you a Supplier<Object>.