FULL PRODUCT VERSION :
java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
OS X 10.9.2
uname -a:
Darwin wpa060009.wireless.mcgill.ca 13.1.0 Darwin Kernel Version 13.1.0: Thu Jan 16 19:40:37 PST 2014; root:xnu-2422.90.20~2/RELEASE_X86_64 x86_64
A DESCRIPTION OF THE PROBLEM :
I have a piece of code using generics (provided below) that under Java 7 (javac -source 1.7) compiles fine, but under Java 8 gives a type error. Also, Eclipse doesn't complain about the code when targeting either java 7 or java 8.
I am not exactly sure whether the code is supposed to compile or not, but at least I'd expect Eclipse and javac to behave consistently, so I imagine one of them has a bug.
Here is the stackoverflow question I asked originally: http://stackoverflow.com/questions/23797972/type-error-using-generics-under-java-8-but-not-java-7
This is the bug submitted to Eclipse (includes some interesting discussion): https://bugs.eclipse.org/bugs/show_bug.cgi?id=435485
REGRESSION. Last worked in version 7u55
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Try to compile the provided test case with javac, with and without passing "-source 1.7". Also try to compile the file in Eclipse 4.4RC1.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expecting javac (-source 1.8) and Eclipse to agree; instead the first gives an error (given below) and the second not.
ACTUAL -
$ javac -source 1.7 Main.java
warning: [options] bootstrap class path not set in conjunction with -source 1.7
1 warning
$ javac -source 1.8 Main.java
Main.java:23: error: method transform in class Iterables cannot be applied to given types;
Iterables.transform(list, AstFunctions.prettyPrint());
^
required: Iterable<F>,Function<? super F,? extends T#1>
found: List<CAP#1>,Function<ASTNode<?>,String>
reason: cannot infer type-variable(s) F,T#1,T#2
(argument mismatch; Function<CAP#1,String> cannot be converted to Function<? super CAP#1,? extends String>)
where F,T#1,T#2 are type-variables:
F extends Object declared in method <F,T#1>transform(Iterable<F>,Function<? super F,? extends T#1>)
T#1 extends Object declared in method <F,T#1>transform(Iterable<F>,Function<? super F,? extends T#1>)
T#2 extends ASTNode<?> declared in method <T#2>prettyPrint()
where CAP#1 is a fresh type-variable:
CAP#1 extends ASTNode<?> from capture of ? extends ASTNode<?>
1 error
No errors in Eclipse.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.Iterator;
class ASTNode<T extends ASTNode> implements Iterable<T> {
@Override public Iterator<T> iterator() { return null; }
}
class List<T extends ASTNode> extends ASTNode<T> {}
interface Function<F, T> {}
class Iterables {
public static <F,T> Iterable<T> transform(
Iterable<F> fromIterable, Function<? super F, ? extends T> function) { return null; }
}
class AstFunctions {
public static <T extends ASTNode<?>> Function<T, String> prettyPrint() { return null; }
}
public class Main {
public static void test() {
List<? extends ASTNode<?>> list = null;
Iterables.transform(list, AstFunctions.prettyPrint());
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
I rewrote the code to use plain loops instead of functional-style Guava code.