Reputation: 3992
When working with some existing code, I've encountered a problem during runtime when running the code with Eclipse Neon.3. Unfortunately, I wasn't able to reproduce the exception in a minimal working example but the following output was produced by the classloader:
Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
...
Reason:
Type 'java/lang/Object' (current frame, stack[8]) is not assignable to 'MyMap'
Current Frame:
...
Bytecode:
...
Stackmap Table:
...
It works on the command line and in older eclipse versions, so it did not matter much at that time. Lasts week, Eclipse Oxygen.1 was released and we started using that one. Now, the same code produces a compile-time exception:
Problem detected during type inference: Unknown error at invocation of reduce(Main.MyMap<MyKey,MyValue>, BiFunction<Main.MyMap<MyKey,MyValue>,? super MyValue,Main.MyMap<MyKey,MyValue>>, BinaryOperator<Main.MyMap<MyKey,MyValue>>)
I've managed to put together a minimal working example that produces this error in Eclipse but works on the commandline:
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
public class Main<MyKey, MyValue> {
static class MyMap<K, V> extends HashMap<K, V> {
public MyMap<K, V> putAllReturning(MyMap<K, V> c) { putAll(c); return this; }
public MyMap<K, V> putReturning(K key, V value) { put(key, value); return this; }
}
public Main() {
Set<MyValue> values = new HashSet<>(); // actually something better
final MyMap<MyKey, MyValue> myMap =
values.stream()
.reduce(
new MyMap<MyKey, MyValue>(),
(map, value) -> {
Set<MyKey> keys = new HashSet<>(); // actually something better
return keys.stream()
.reduce(
map, // this would work syntactically: new MyMap<MyKey, MyValue>(),
(map2, key) -> map2.putReturning(key, value),
MyMap::putAllReturning);
},
MyMap::putAllReturning
);
}
}
It seems that the first parameter to the inner reduce causes type-inference to break, as replacing it with another instance of the same type (but explicitly declared instead of inferred) eliminates the error.
Knowing the exact source of the error in the class allowed us to rewrite the code (extracting the lambda expression passed to the outer reduce to its own method). However, I'd still be interested in an explanation to why such a construct might break both of the newer eclipse compilers.
Upvotes: 3
Views: 1183
Reputation: 120848
Well for me on Oxygen
, it worked by simply declaring the parameters for the reduce:
(MyMap<MyKey, MyValue> map, MyValue value) -> ....
Knowing the exact problem and why eclipse compiler can't infer the types is too much for me; either way this should be reported (it might be already known by the eclipse team).
I can also confirm that it compiles OK with jdk-8-131
and jdk-9-175
Upvotes: 3