Florin M
Florin M

Reputation: 189

Incompatible types when using lower bound wildcard

I can't understand why I have a compilation error for this code:

private static <T> Consumer<T> f3()
{
    return t -> {};
}

private static <T> Consumer<? super T> f4()
{
    return t -> {};
}


@Test
public void test()
{
    Consumer<Integer> action3 = f3();
    Consumer<Integer> action4 = f4(); // ERROR
}

the error from javac 1.8.0_161:

Error:(84, 36) java: incompatible types: no instance(s) of type variable(s) T exist so that java.util.function.Consumer<? super T> conforms to java.util.function.Consumer<java.lang.Void>

Can anyone explain this error? Thanks.

EDIT I tried to simplify my example, and I did an error by making it too simple. What I'm interested is an explanation for this error which is output by IntelliJ:

private static <T> BiConsumer<T, ? super Throwable> f1(Consumer<? super Throwable> consumer)
{
    return null;
}

private static <T> BiConsumer<? super T, ? super Throwable> f2(Consumer<? super Throwable> consumer)
{
    return null;
}

@Test
public void test()
{
    BiConsumer<? super Integer, ? super Throwable> action1 = f1(throwable -> { });
    BiConsumer<? super Integer, ? super Throwable> action2 = f2(throwable -> { });  // ERROR HERE
}

IntelliJ considers this an error because "inference variable T has incompatible bounds: equality constraints: T lower bounds: Integer". But when compiling it, it's fine, no error. Is this an actually valid Java code and just a bug in IntelliJ? Thanks.

Upvotes: 2

Views: 1024

Answers (3)

Pushpendra Jaiswal
Pushpendra Jaiswal

Reputation: 470

Please try File->Invalidate Caches and restart.

Upvotes: 0

Andy Turner
Andy Turner

Reputation: 140328

An answer for your edit:

I suspect this is a bug in intellij. If I remove the variable declaration, and then select the expression and press Ctrl+Alt+V to extract a variable, it picks the following type:

BiConsumer<? super Object, ? super Throwable> biConsumer = f2(throwable -> {});

which, despite just having picked itself, it highlights the lambda as an error.

Upvotes: 1

Andy Turner
Andy Turner

Reputation: 140328

A Consumer<? super Something> isn't a Consumer<Integer>.

The compiler doesn't know that there are no producer methods on the Consumer class, so it stops you potentially using it as a producer.

As far as the type inference rules are concerned, there is no difference between Consumer and List, for example. So the same rule which stops you writing the following also stops you in what you are doing:

List<? super Integer> c = Arrays.asList("");
List<Integer> d = c;        // Compiler error; let's pretend it works.
Integer i = d.get(0);       // ClassCastException!

Upvotes: 5

Related Questions