JDK-8159680 : Inference failure with unchecked subtyping and arrays
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 9
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: x86
  • Submitted: 2016-06-15
  • Updated: 2019-08-02
  • Resolved: 2016-06-17
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.
JDK 9
9 b124Fixed
Related Reports
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "9-ea"
Java(TM) SE Runtime Environment (build 9-ea+122)
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+122, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Mac OS X 10.11.5

A DESCRIPTION OF THE PROBLEM :
Code which uses generics, varargs, and overloaded methods compiles on JDK 8 but fails to compile on JDK 9-ea+122.

Specifically, within the compose() method in the supplied Test class, the following line of code compiles on JDK 8 and 9:

Test.<Number> allOf(conditions);

But the following line does not compile on JDK 9:

allOf(conditions);

REGRESSION.  Last worked in version 8u92

ADDITIONAL REGRESSION INFORMATION: 
java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
javac Test.java

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expect the supplied Test class to compile on JDK 9.
ACTUAL -
The supplied Test class does not compile on JDK 9.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Test.java:22: error: no suitable method found for allOf(Test.Condition<? super Number>[])
		allOf(conditions);
		^
    method Test.<T#1>allOf(Test.Condition<? super T#1>...) is not applicable
      (cannot infer type-variable(s) T#1
        (varargs mismatch; Test.Condition<? super Number>[] cannot be converted to Test.Condition<? super T#1>))
    method Test.<T#2>allOf(Iterable<? extends Test.Condition<? super T#2>>) is not applicable
      (cannot infer type-variable(s) T#2
        (argument mismatch; Test.Condition<? super Number>[] cannot be converted to Iterable<? extends Test.Condition<? super T#2>>))
  where T#1,T#2 are type-variables:
    T#1 extends Object declared in method <T#1>allOf(Test.Condition<? super T#1>...)
    T#2 extends Object declared in method <T#2>allOf(Iterable<? extends Test.Condition<? super T#2>>)
1 error

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class Test {

	public class Condition<T> {}

	@SafeVarargs
	public static <T> Condition<T> allOf(Condition<? super T>... conditions) {
		return null;
	}

	public static <T> Condition<T> allOf(Iterable<? extends Condition<? super T>> conditions) {
		return null;
	}

	@SafeVarargs
	public static Condition<Number> compose(Condition<? super Number>... conditions) {

		// Compiles on JDK 8 and JDK 9
		Test.<Number> allOf(conditions);

		// Compiles on JDK 8 but *fails* on JDK 9
		allOf(conditions);

		return null;
	}
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
The workaround is to explicitly supply the generic type (i.e., <Number>) as follows.

Test.<Number> allOf(conditions);


Comments
On a closer look, I'm not sure the current behavior is legitimate. The compiler seems to perform an extra capture conversion when checking as to whether Condition<? super Number>[] is an unchecked subtype of Condition<? super T>[]; capture conversion is typically performed when entering a subtyping check, but it's never performed recursively on arrays during standard subtyping. However there's a discrepancy between the routine used by javac to do unchecked subtyping and that used for doing subtyping; and the former will recursively invoke subtyping on the element types of the arrays, which will then cause captured variables to pop up in places which are not possible during regular subtyping between arrays. While the theoretical side of handling captured variables in subtyping should be handled by JDK-8154901, I think that, implementation-wise, for the time being javac should at least apply capture consistently between unchecked and regular subtyping.
16-06-2016

This is an issue in 9 and not not applicable to 8 8uxx - Pass 9 ea b122 - Fail -sh-4.1$ /opt/java/jdk1.8.0_92/bin/javac Test.java -sh-4.1$ /opt/java/jdk-9_ea-122/bin/javac Test.java Test.java:21: error: no suitable method found for allOf(Test.Condition<? super Number>[]) allOf(conditions); ^ method Test.<T#1>allOf(Test.Condition<? super T#1>...) is not applicable (cannot infer type-variable(s) T#1 (varargs mismatch; Test.Condition<? super Number>[] cannot be converted to Test.Condition<? super T#1>)) method Test.<T#2>allOf(Iterable<? extends Test.Condition<? super T#2>>) is not applicable (cannot infer type-variable(s) T#2 (argument mismatch; Test.Condition<? super Number>[] cannot be converted to Iterable<? extends Test.Condition<? super T#2>>)) where T#1,T#2 are type-variables: T#1 extends Object declared in method <T#1>allOf(Test.Condition<? super T#1>...) T#2 extends Object declared in method <T#2>allOf(Iterable<? extends Test.Condition<? super T#2>>) 1 error -sh-4.1$
16-06-2016

More precise type-containment check added in JDK-8039214 makes inference fail.
16-06-2016