JDK-8251891 : Lower bound containing wildcard get lost during type inference
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8-pool,11,14,16
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: x86_64
  • Submitted: 2020-08-16
  • Updated: 2021-06-09
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Related Reports
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
$ javac --version
javac 14.0.2
$ java --version
openjdk 14.0.2 2020-07-14
OpenJDK Runtime Environment (build 14.0.2+12-Debian-1)
OpenJDK 64-Bit Server VM (build 14.0.2+12-Debian-1, mixed mode, sharing)
$ uname -a
Linux xxxxxx 5.7.0-1-amd64 #1 SMP Debian 5.7.6-1 (2020-06-24) x86_64 GNU/Linux


A DESCRIPTION OF THE PROBLEM :
It's hard to pinpoint the issue specifically, but it seems that somehow lower bound of type variable that contains wildcard get lost during type inference and as a result unification fail.

The problem is frustrating because there seems to be no workaround besides duplicating and inlining the code.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
The problem can be reproduced by compiling the test program.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
It is expected that this program should compile. In the `requireUniquieTs` method body `V` type-variable should have lower-bound `HasT<CAP#1>`. When calling `requireUniquieTsTyped` javac should try to unify `V#1 extends HasT<CAP#1>` and `V#1 extends HasT<T#1>` and derive that `T#1 = CAP#1`.
ACTUAL -
Running javac results in the following error:

````
HasT.java:7: error: method requireUniquieTsTyped in interface HasT<T#2> cannot be applied to given types;
        return requireUniquieTsTyped(vs);
               ^
  required: Set<V#1>
  found:    Set<V#2>
  reason: inference variable V#1 has incompatible bounds
    equality constraints: V#2
    lower bounds: HasT<T#1>
  where V#1,T#1,V#2,T#2 are type-variables:
    V#1 extends HasT<T#1> declared in method <V#1,T#1>requireUniquieTsTyped(Set<V#1>)
    T#1 extends Object declared in method <V#1,T#1>requireUniquieTsTyped(Set<V#1>)
    V#2 extends HasT<?> declared in method <V#2>requireUniquieTs(Set<V#2>)
    T#2 extends Object declared in interface HasT
1 error
````



---------- BEGIN SOURCE ----------
import java.util.Set;

interface HasT<T> {
    static
    <V extends HasT<?>>
    Set<V> requireUniquieTs(Set<V> vs) {
        return requireUniquieTsTyped(vs);
    }

    static
    <V extends HasT<T>, T>
    Set<V> requireUniquieTsTyped(Set<V> vs) {
        throw new UnsupportedOperationException("Not implemented");
    }

    T getT();
}

---------- END SOURCE ----------

FREQUENCY : always



Comments
Simplified test case: public class JDK8251891 { interface I<T> {} interface J<T> {} static <X extends I<?>> void test(J<X> vs) { m(vs); } static <Y extends I<T>, T> void m(J<Y> vs) { } }
09-06-2021

The behavior of inference here is unspecified: what is the supertype of 'V extends HasT<?>' that is a typed (non-wildcard) parameterization of 'HasT'? JDK-8016196 explores this issue further.
09-06-2021

Compilation of above code gives compilation error: required: Set<V#1> found: Set<V#2> reason: inference variable V#1 has incompatible bounds equality constraints: V#2 lower bounds: HasT<T#1> where V#1,T#1,V#2,T#2 are type-variables: V#1 extends HasT<T#1> declared in method <V#1,T#1>requireUniquieTsTyped(Set<V#1>) T#1 extends Object declared in method <V#1,T#1>requireUniquieTsTyped(Set<V#1>) V#2 extends HasT<?> declared in method <V#2>requireUniquieTs(Set<V#2>) T#2 extends Object declared in interface HasT It can be seen in Oracle JDK 8 to 16 as well.
17-08-2020