I'd like to resolve a dubious point that has been affecting some parts of my code for years — it is fixed with a trivial cast, but now I'd like to understand the rationale behind it and possibly a reference in official specifications.
Let me introduce this piece of code:
import java.util.function.Supplier;
class BaseClass<T, R> {
  R getSomething() { return null; }
  static <U> U method1 (final U arg1) { return arg1; }
  static <U> U method2 (final U arg1, final Class<? extends U> arg2) { return arg1; }
  static <U> U method3 (final U arg1, final Supplier<? extends U> arg2) { return arg1; }
}
Now let me have a subclass with a partial generics binding (T is still unbound):
class DerivedClass<T> extends BaseClass<T, String> {
  private String s;
  void test (final DerivedClass<T> arg) {
    final var m1 = method1(arg);
    s = m1.getSomething();
    final DerivedClass<T> m3 = method1(arg);
    s = m3.getSomething();
    final var m2 = method2(arg, DerivedClass.class);
    // 1. ERROR: requires String, found Object
    s = m2.getSomething();
    // 2. WARNING: unchecked assignment DerivedClass to DerivedClass<T>
    final DerivedClass<T> m4 = method2(arg, DerivedClass.class);
    s = m4.getSomething();
    final var m5 = method3(arg, () -> new DerivedClass<>());
    s = m5.getSomething();
    } 
}
With method1 everything is fine and the returned object carries the binding R -> String. In other words, the U type of arg1 is correctly propagated to the result.
With method2 the binding is lost (and "downgraded" to Object): this ends up in a warning if I force things with an explicit type declaration of m4 (of course an explicit cast would work too) and an error if I use var.
With method3, in spite of arg2 being declared in a similar way as in method2, everything is fine again.
So it seems that the culprit is the presence of an argument of Class<> type. Why? In general, why doesn't the compiler use arg1 for a complete match even when there is a Class<> parameter?
As far as I can remember this happens since Java 5 (of course the portions with var refer to Java 17).
 
     
     
    