I have this class that simplifies some code that I found in a project that migrates from Java 6 to Java 8:
public class Unification { final class Box<A> {} final class MyMap<A, B extends Box<? extends A>> {} MyMap<?, ?> getMap() { return new MyMap<Object, Box<Object>>(); } <A, B extends Box<? extends A>> void setMap(final MyMap<A, B> m) {} void compileError() { setMap(getMap()); } }
This is a very small example, just to demonstrate the problem, the actual code makes a little more sense. The question seems to be a fairly general, although, therefore, abstract example. The main problem is this: for some reason, javac does not want to accept an expression of type MyMap<?, ?> As an argument to the setMap() method, although this should, in my opinion, be well-typed.
The code compiles without errors using javac 6, but I get this obscure error message when I use javac 8:
C:\System9\KWS_sparse\sourcesNG\Domain\src\uz\Unification.java (21:9) error: method setMap in class Unification cannot be applied to given types; required: Unification.MyMap<A,B> found: Unification.MyMap<CAP#1,CAP#2> reason: inference variable A has incompatible bounds equality constraints: CAP#1 lower bounds: Object where A,B are type-variables: A extends Object declared in method <A,B>setMap(Unification.MyMap<A,B>) B extends Unification.Box<? extends A> declared in method <A,B>setMap(Unification.MyMap<A,B>) where CAP#1,CAP#2 are fresh type-variables: CAP#1 extends Object from capture of ? CAP#2 extends Unification.Box<? extends CAP#1> from capture of ?
The error message seems to indicate that for a parameter of the first type MyMap no unification was found, javac cannot find a type that combines with both CAP#1 , which represents the first substitution argument in the actual parameter setMap() and A , which is the corresponding parameter of the type of the formal parameter setMap() . Although it seems to me that A and CAP#1 should be completely unified, they will then be an existential type, introduced by erasing the actual types in the getMap() signature.
Can anyone determine what is going on here? Has javac 6 mistakenly accepted this code? Also, is there a not-too-intrusive (and javac 6 compatible) way to guide javac 8 toward proper unification?
EDIT: I tried to suggest introducing a variable from stackoverflow.com/questions/23063474/, but that doesn't seem to help, I get the same compilation error.
EDIT2: Clarified the "intent" of the sample code.
EDIT3: Renamed Map to MyMap , it seems too difficult to introduce a native Map type.