6932571: Compiling Generics causing Inconvertible types
authormcimadamore
Mon, 23 Aug 2010 16:59:30 +0100
changeset 6353 bb5c39054bf3
parent 6352 217d5a69681a
child 6354 f50c012cd1f0
6932571: Compiling Generics causing Inconvertible types Summary: Types.rewriteQuantifiers() does not work well with recursive type-variable bounds Reviewed-by: jjg
langtools/src/share/classes/com/sun/tools/javac/code/Type.java
langtools/src/share/classes/com/sun/tools/javac/code/Types.java
langtools/test/tools/javac/cast/6270087/T6270087.java
langtools/test/tools/javac/cast/6270087/T6270087neg.java
langtools/test/tools/javac/cast/6270087/T6270087neg.out
langtools/test/tools/javac/cast/6507317/T6507317.java
langtools/test/tools/javac/cast/6569057/T6569057.java
langtools/test/tools/javac/cast/6932571/T6932571a.java
langtools/test/tools/javac/cast/6932571/T6932571b.java
langtools/test/tools/javac/cast/6932571/T6932571neg.java
langtools/test/tools/javac/cast/6932571/T6932571neg.out
--- 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