Cannot infer type-variable(s) generics issue in Java

Viewed 41

This question may have some similar ones, but I hope you can look at the code structure here and provide some insight. I believe this either demonstrates a very subtle user error, or a very subtle unaddressed issue in the Java type system. This is a case in which Java struggles to infer the type of an argument passed into a method with the error message:

java: method process in class Usage cannot be applied to given types;
  required: OuterWrapper<C,InnerWrapper<C>>
  found: RealOuterWrapper
  reason: cannot infer type-variable(s) C
    (argument mismatch; RealOuterWrapper cannot be converted to OuterWrapper<C,InnerWrapper<C>>)

One interesting detail is that very similar code (listed at the bottom) does compile and run.

Usage.java:

public static <C extends Model> void process (OuterWrapper<C, InnerWrapper<C>> wrapper) {
    ;
}

public static void main(String[] args) {
    process(new RealOuterWrapper());
}

OuterWrapper.java:

public interface OuterWrapper <T extends Model, D extends InnerWrapper<T> >{}

RealOuterWrapper.java:

public class RealOuterWrapper implements OuterWrapper<RealModel, RealInnerWrapper>{}

InnerWrapper.java:

public interface InnerWrapper <T extends Model>{}

RealInnerWrapper.java:

public interface RealInnerWrapper extends InnerWrapper<RealModel>{}

Model.java:

public interface Model {}

RealModel.java:

public class RealModel implements Model {}

This code fails to compile. However, this code compiles successfully:


Usage.java:

public class Usage {
    public static <C extends Model> void process (Wrapper<C,C> wrapper) {
        ;
    }

    public static void main(String[] args) {
        process(new RealWrapper());
    }
}

Wrapper.java:

public interface Wrapper <A extends Model,B extends Model>{}

RealWrapper.java:

public class RealWrapper implements Wrapper<RealModel,RealModel>{}

Model.java:

public interface Model {}

RealModel.java:

public class RealModel implements Model {}

Finally, if this wall of text is too hard to reason about, here is my GitHub repo containing these files!


Edit: Rewriting RealInnerWrapper as a class that implements InnerWrapper, I added

Usage.java:

public static void main(String[] args) {
    process(new RealOuterWrapper());
    process2(new RealInnerWrapper());
}
public static void process2 (InnerWrapper<RealModel> wrapper) {
    ;
}

However, the latter method process2 gives no such error, which implies a RealInnerWrapper() is an InnerWrapper<RealModel>.

0 Answers
Related