JDK-8166437 : Regression in javac - inferring generic types in Guava
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 9
  • Priority: P2
  • Status: Resolved
  • Resolution: Duplicate
  • Submitted: 2016-09-21
  • Updated: 2016-12-01
  • Resolved: 2016-12-01
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
9Resolved
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
# Prerequisites
having git, maven installed.
# Steps
git clone https://github.com/google/guava.git
mvn clean install

Guava can be successfully built in jdk8, and jdk9.b12. It start to fail in jdk9.b13, different versions of jdk9 builds have different errors(for detailed information please check comments). It seems not the same issue as JDK-8160244/JDK-8165756.
Below is the error messages in jdk9.b136 (for full log please check attachment and comments):

[ERROR] /home/oracle/workspace/jdk/3rd.party.tools/guava/guava.jdk9/guava/src/com/google/common/collect/Collections2.java:[288,20] error: method all in class Iterables cannot be applied to given types;
[ERROR] 
    CAP#1 extends Object from capture of ?
    CAP#2 extends Object from capture of ?
/home/oracle/workspace/jdk/3rd.party.tools/guava/guava.jdk9/guava/src/com/google/common/collect/Sets.java:[1188,50] error: incompatible types: ImmutableSet<CAP#1> cannot be converted to ImmutableSet<E>
[ERROR] 
    CAP#1 extends E from capture of ? extends E
/home/oracle/workspace/jdk/3rd.party.tools/guava/guava.jdk9/guava/src/com/google/common/collect/Maps.java:[500,46] error: incompatible types: SortedMap<K,CAP#1> cannot be converted to Map<K,V>
..........(hide many error messages)............

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
To reproduce the issue(first error reported in Collections2.java) in a simple scenario, below code(class hierarchy) is extracted from Guava, but the issue can not be reproduced.

interface Predicate<T> {
}

class InPredicate<T> implements Predicate<T> {
    private final Collection<?> target;

    InPredicate(Collection<?> target) {
      this.target = target;
    }
}

final class Iterables {
	public static <T> boolean all(Iterable<T> iterable, Predicate<? super T> predicate) {
		return true;
	}
}

final class Predicates {
	public static <T> Predicate<T> in(Collection<? extends T> target) {
		return new InPredicate<T>(target);
	}
}

final class Collections2 {
	static boolean containsAllImpl(Collection<?> self, Collection<?> c) {
		return Iterables.all((Iterable<?>) c, Predicates.in(self));
	}
}

Comments
Addressing this via JDK-8075793.
01-12-2016

See also JDK-8075793, which was the same issue.
03-10-2016

A stripped-down case: abstract <T> List<T> wrap(List<? extends T> l); void test(List<? extends Runnable> l) { List<Runnable> lr = wrap(l); } It doesn't work because that's not how inference pre-8 ever worked: pass a List<CAP> in to 'wrap', and you should get out a List<CAP>. It's unfortunate that javac added some unspecified behaviors that made it compile...
03-10-2016

Expanded test case to remove library dependency: import java.util.*; class Test { private static <K1, V1> Map<K1, V1> unmodifiableMap(Map<K1, ? extends V1> map) { return unmodifiableMap2(map); } public static <K2,V2> Map<K2,V2> unmodifiableMap2(Map<? extends K2,? extends V2> m) { return null; } } Constraints are computed as follows: K1 <= ? extends K2 K1 <: K2 #CAP1 <= ? extends V2, where #CAP1 is capture of ? extends V1 #CAP1 <: V2 In JDK 8 we get additional constraints (from target typing): K2 = K1 V2 = V2 So, in 9 we infer K2 = K1, and V2 = V1. But in 7 we infer K2 = K1 and V2 = #CAP1. Hence the error (as Map<K1, #CAP1> is not compatible with Map<K, V>). This is ultimately a side-effect of JDK-8039214.
03-10-2016

Got it - the problem is only reproducible with the compiler flag -source 6/7. Minimal test case: import java.util.*; class Test { private static <K, V> Map<K, V> unmodifiableMap(Map<K, ? extends V> map) { return Collections.unmodifiableMap(map); } } Gives: error: incompatible types: Map<K,CAP#1> cannot be converted to Map<K,V> return Collections.unmodifiableMap(map); ^ where K,V are type-variables: K extends Object declared in method <K,V>unmodifiableMap(Map<K,? extends V>) V extends Object declared in method <K,V>unmodifiableMap(Map<K,? extends V>) where CAP#1 is a fresh type-variable: CAP#1 extends V from capture of ? extends V 1 error But compiles when source 8 or 9 is used (where target typing is enabled).
03-10-2016

I'm not sure about what's happening. I'm able to reproduce the issue (to do that I have to set JAVA_HOME to point to JDK 9, which I don't know as to whether is the right thing to do - does maven support JDK 9 in the first place?) For instance I get inference errors in the following method in Maps.java: private static <K, V> Map<K, V> unmodifiableMap(Map<K, ? extends V> map) { if (map instanceof SortedMap) { return Collections.unmodifiableSortedMap((SortedMap<K, ? extends V>) map); //error here } else { return Collections.unmodifiableMap(map); //another error here } } Note that this method does not depend on Guava libraries and can be cut and pasted onto a standalone test. However, once you do that, no error occurs - i.e. the above snippet does compile under JDK 9.
03-10-2016

I tried to reduce it with just class hierarchy, but it can not be reproduced. (please check the sample code in Description)
22-09-2016

Can you reduce this to a test case that does not require the use of git or maven?
22-09-2016