6932571: Compiling Generics causing Inconvertible types
Summary: Types.rewriteQuantifiers() does not work well with recursive type-variable bounds
Reviewed-by: jjg
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java Thu Aug 19 11:54:25 2010 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java Mon Aug 23 16:59:30 2010 +0100
@@ -328,6 +328,10 @@
return (tsym.flags() & INTERFACE) != 0;
}
+ public boolean isFinal() {
+ return (tsym.flags() & FINAL) != 0;
+ }
+
public boolean isPrimitive() {
return tag < VOID;
}
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Thu Aug 19 11:54:25 2010 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Mon Aug 23 16:59:30 2010 +0100
@@ -960,7 +960,7 @@
return true;
if (s.tag == TYPEVAR) {
- if (isCastable(s.getUpperBound(), t, Warner.noWarnings)) {
+ if (isCastable(t, s.getUpperBound(), Warner.noWarnings)) {
warnStack.head.warnUnchecked();
return true;
} else {
@@ -1030,7 +1030,12 @@
&& !disjointTypes(aHigh.allparams(), lowSub.allparams())
&& !disjointTypes(aLow.allparams(), highSub.allparams())
&& !disjointTypes(aLow.allparams(), lowSub.allparams())) {
- if (upcast ? giveWarning(a, b) :
+ if (s.isInterface() &&
+ !t.isInterface() &&
+ t.isFinal() &&
+ !isSubtype(t, s)) {
+ return false;
+ } else if (upcast ? giveWarning(a, b) :
giveWarning(b, a))
warnStack.head.warnUnchecked();
return true;
@@ -1230,18 +1235,23 @@
if (t == s) return false;
if (t.tag == TYPEVAR) {
TypeVar tv = (TypeVar) t;
- if (s.tag == TYPEVAR)
- s = s.getUpperBound();
return !isCastable(tv.bound,
- s,
+ relaxBound(s),
Warner.noWarnings);
}
if (s.tag != WILDCARD)
s = upperBound(s);
- if (s.tag == TYPEVAR)
- s = s.getUpperBound();
-
- return !isSubtype(t, s);
+
+ return !isSubtype(t, relaxBound(s));
+ }
+
+ private Type relaxBound(Type t) {
+ if (t.tag == TYPEVAR) {
+ while (t.tag == TYPEVAR)
+ t = t.getUpperBound();
+ t = rewriteQuantifiers(t, true, true);
+ }
+ return t;
}
// </editor-fold>
@@ -3280,7 +3290,7 @@
* quantifiers) only
*/
private Type rewriteQuantifiers(Type t, boolean high, boolean rewriteTypeVars) {
- return new Rewriter(high, rewriteTypeVars).rewrite(t);
+ return new Rewriter(high, rewriteTypeVars).visit(t);
}
class Rewriter extends UnaryVisitor<Type> {
@@ -3293,25 +3303,21 @@
this.rewriteTypeVars = rewriteTypeVars;
}
- Type rewrite(Type t) {
- ListBuffer<Type> from = new ListBuffer<Type>();
- ListBuffer<Type> to = new ListBuffer<Type>();
- adaptSelf(t, from, to);
+ @Override
+ public Type visitClassType(ClassType t, Void s) {
ListBuffer<Type> rewritten = new ListBuffer<Type>();
- List<Type> formals = from.toList();
boolean changed = false;
- for (Type arg : to.toList()) {
+ for (Type arg : t.allparams()) {
Type bound = visit(arg);
if (arg != bound) {
changed = true;
- bound = high ? makeExtendsWildcard(bound, (TypeVar)formals.head)
- : makeSuperWildcard(bound, (TypeVar)formals.head);
}
rewritten.append(bound);
- formals = formals.tail;
}
if (changed)
- return subst(t.tsym.type, from.toList(), rewritten.toList());
+ return subst(t.tsym.type,
+ t.tsym.type.allparams(),
+ rewritten.toList());
else
return t;
}
@@ -3322,13 +3328,22 @@
@Override
public Type visitCapturedType(CapturedType t, Void s) {
- return visitWildcardType(t.wildcard, null);
+ Type bound = visitWildcardType(t.wildcard, null);
+ return (bound.contains(t)) ?
+ (high ? syms.objectType : syms.botType) :
+ bound;
}
@Override
public Type visitTypeVar(TypeVar t, Void s) {
- if (rewriteTypeVars)
- return high ? t.bound : syms.botType;
+ if (rewriteTypeVars) {
+ Type bound = high ?
+ (t.bound.contains(t) ?
+ syms.objectType :
+ visit(t.bound)) :
+ syms.botType;
+ return rewriteAsWildcardType(bound, t);
+ }
else
return t;
}
@@ -3338,11 +3353,31 @@
Type bound = high ? t.getExtendsBound() :
t.getSuperBound();
if (bound == null)
- bound = high ? syms.objectType : syms.botType;
- return bound;
+ bound = high ? syms.objectType : syms.botType;
+ return rewriteAsWildcardType(visit(bound), t.bound);
+ }
+
+ private Type rewriteAsWildcardType(Type bound, TypeVar formal) {
+ return high ?
+ makeExtendsWildcard(B(bound), formal) :
+ makeSuperWildcard(B(bound), formal);
+ }
+
+ Type B(Type t) {
+ while (t.tag == WILDCARD) {
+ WildcardType w = (WildcardType)t;
+ t = high ?
+ w.getExtendsBound() :
+ w.getSuperBound();
+ if (t == null) {
+ t = high ? syms.objectType : syms.botType;
+ }
+ }
+ return t;
}
}
+
/**
* Create a wildcard with the given upper (extends) bound; create
* an unbounded wildcard if bound is Object.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/cast/6270087/T6270087.java Mon Aug 23 16:59:30 2010 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6270087 6932571
+ * @summary Javac rejects legal cast
+ * @compile T6270087.java
+ */
+
+class T6270087 {
+
+ static class Foo<X> {}
+
+ <S extends Comparable<S>> void test1(Comparable<Integer> c) {
+ Object o = (Comparable<S>)c;
+ }
+
+ <U extends Throwable, V extends Runnable> void test2(Foo<V> lv) {
+ Object o = (Foo<U>) lv;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/cast/6270087/T6270087neg.java Mon Aug 23 16:59:30 2010 +0100
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6270087 6932571
+ * @summary Javac rejects legal cast
+ * @compile/fail/ref=T6270087neg.out -XDrawDiagnostics T6270087neg.java
+ */
+
+class T6270087neg {
+
+ static class Foo<X> {}
+
+ <U extends Integer, V extends String> void test2(Foo<V> lv) {
+ Object o = (Foo<U>) lv;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/cast/6270087/T6270087neg.out Mon Aug 23 16:59:30 2010 +0100
@@ -0,0 +1,2 @@
+T6270087neg.java:36:29: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6270087neg.Foo<V>, T6270087neg.Foo<U>
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/cast/6507317/T6507317.java Mon Aug 23 16:59:30 2010 +0100
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6507317 6932571
+ * @summary Problem when casting from parametrized type to concrete class
+ * @compile T6507317.java
+ */
+
+import java.util.Comparator;
+
+abstract class T6507317<T extends Comparable<T>> implements Comparator<T> {
+ void test(T t) {
+ String s = (String)t;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/cast/6569057/T6569057.java Mon Aug 23 16:59:30 2010 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6569057 6932571
+ * @summary Generics regression on cast
+ * @compile T6569057.java
+ */
+
+class T6569057 {
+ static class A<X extends B<?>> { }
+
+ static class B<X extends A<?>> {
+ D<? extends B<X>> get() { return null; }
+ }
+
+ static class D<Y extends B<?>> {}
+
+ <E extends B<?>> void test(E x, D<B<A<?>>> d) {
+ boolean b = x.get() == d;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/cast/6932571/T6932571a.java Mon Aug 23 16:59:30 2010 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6932571
+ * @summary Compiling Generics causing Inconvertible types
+ * @compile T6932571a.java
+ */
+
+class T6932571a {
+ static class A<T extends Comparable<? super T>> {
+ public void test(T v) {
+ Object obj = (Integer)v;
+ }
+ }
+
+ static class B<T extends Comparable<? extends T>> {
+ public void test(T v) {
+ Object obj = (Integer)v;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/cast/6932571/T6932571b.java Mon Aug 23 16:59:30 2010 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6932571
+ * @summary Compiling Generics causing Inconvertible types
+ * @compile T6932571b.java
+ */
+
+class T6932571b {
+
+ interface A1<T extends B<? super T>> {
+ public T getT();
+ }
+
+ interface A2<T extends B<? extends T>> {
+ public T getT();
+ }
+
+ class B<T extends B<T>> {}
+
+ class C extends B<C> {}
+
+ void test1(A1<?> a) {
+ Object o = (C)a.getT();
+ }
+
+ void test2(A2<?> a) {
+ Object o = (C)a.getT();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/cast/6932571/T6932571neg.java Mon Aug 23 16:59:30 2010 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6932571
+ * @summary Compiling Generics causing Inconvertible types
+ * @compile/fail/ref=T6932571neg.out -XDrawDiagnostics T6932571neg.java
+ */
+
+class T6932571neg {
+ interface I<T>{ }
+ interface I1 extends I<String> {}
+ static class Y implements I<String> {}
+ final static class S implements I<String> {}
+
+ <G extends I<G>> void test() {
+ S s = new S();
+ G g = (G) s;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/cast/6932571/T6932571neg.out Mon Aug 23 16:59:30 2010 +0100
@@ -0,0 +1,2 @@
+T6932571neg.java:39:19: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6932571neg.S, G
+1 error