More type inference changes
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Wed Feb 3 21:54:34 UTC 2016
Adding Dan
On 03/02/16 18:41, Liam Miller-Cushon wrote:
> I noticed three more javac9 type inference incompatibilities, each of
> which only occurs once in the codebase I've been testing against.
>
> 1) The following code is rejected by javac9 at head, and accepted by
> earlier versions. The first bad revision is 3211.
>
> http://hg.openjdk.java.net/jdk9/dev/langtools/rev/3211
> http://bugs.openjdk.java.net/browse/JDK-8147493
>
> abstract class Test {
>
> interface O<A> {}
> interface R<B> {}
> interface S<C> { S<C> t(C x); }
> abstract <D> D a(Class<D> methodCall);
> abstract R<Number> g(O<Number> q, String s);
> abstract <E> S<E> w(E m);
>
> S<R<Number>> f(R<Number> r) {
> return w(g(a(O.class), a(String.class))).t(r);
> }
> }
>
> error: incompatible types: S<R> cannot be converted to S<R<Number>>
> return w(g(a(O.class), a(String.class))).t(r);
This looks ok to me?
I.e. the call to 'a' with O.class is fine (not unchecked) - but the next
call to 'g' is unchecked, as the return type for 'a' is simply O and the
target type is O<Number> - that triggers the unchecked call and that
means that the return type of 'g' is erased to R, and then the inference
variable of 'w' (E) is inferred as R, meaning that the return type is
S<R> - which means the signature of 't' inside S<R> is (R)S<R>, so
indeed the return type of that method (S<R>) seems not compatible with
the return type of your 'f' (S<R<Number>>). Would you agree?
> ^
>
> 2) This is also rejected at head, and accepted by earlier versions.
> The first bad revision is 3030.
>
> http://hg.openjdk.java.net/jdk9/dev/langtools/rev/3030
> http://bugs.openjdk.java.net/browse/JDK-8078093
>
> abstract class Test {
>
> interface One<A> {}
> interface Two<B extends Three, C extends Four> {}
> interface Three {}
> interface Four {}
> abstract <D> One<D> h(Class<D> clazz);
> abstract void g(One<? extends Two<Three, Four>> x);
>
> void f() {
> g(h(Two.class));
> }
> }
>
> error: incompatible types: One<Two> cannot be converted to One<?
> extends Two<Three,Four>>
> g(h(Two.class));
> ^
On this one, I'm also not sure: h(Two.class) means that D is inferred as
the raw Two. So 'h' returns One<Two>. Is One<Two> compatible with One<?
extends Two<Three, Four>> ? This essentially means asking as to whether
Two <: Two<Three, Four>
Since containment use strict subtyping, and not unchecked, I think this
means that this is not compatible? [For what it's worth, Eclipse agrees
on this one]
>
>
> 3) This one is accepted at head, and also by earlier versions. It was
> briefly rejected between 3030 and 3109. Was the fix in 3109 deliberate?
I don't think it was deliberate to change this (in both changesets), so
I will need to study the inference graphs before/after; Eclipse hangs
(at least the version I tried to use) when compiling this. It seems like
this should pass - an extra synthetic inference variable should be
introduced for the wildcard, so that it's One<A, U> <: One<D, E>, which
means:
A == D
U == E
and they are all inferred as Object.
Maurizio
>
> First bad revision:
> http://hg.openjdk.java.net/jdk9/dev/langtools/rev/3030
> https://bugs.openjdk.java.net/browse/JDK-8078093
>
> First good revision:
> http://hg.openjdk.java.net/jdk9/dev/langtools/rev/3109
> http://bugs.openjdk.java.net/browse/JDK-8067767
>
> abstract class Test {
>
> interface One<G, H extends One<G, H>> {}
> abstract <D, E extends One<D, E>> void g(One<D, E> f);
> abstract <A> One<A, ?> h();
>
> void f() {
> g(h());
> }
> }
>
> error: method g in class Test cannot be applied to given types;
> g(h());
> ^
> required: One<D,E#1>
> found: One<Object,CAP#1>
> reason: inferred type does not conform to upper bound(s)
> inferred: E#2
> upper bound(s): One<Object,E#2>,One<Object,<captured wildcard>>
> where D,E#1,E#2,<captured wildcard> are type-variables:
> D extends Object declared in method <D,E#1>g(One<D,E#1>)
> E#1 extends One<D,E#1> declared in method <D,E#1>g(One<D,E#1>)
> E#2 extends One<Object,<captured wildcard>>
> <captured wildcard> extends One<Object,E#2>
> where CAP#1 is a fresh type-variable:
> CAP#1 extends One<Object,CAP#1> from capture of ?
>
More information about the compiler-dev
mailing list