8141343: Subtle semantics changes for union types in cast conversion
authormcimadamore
Thu, 05 Nov 2015 11:32:01 +0000
changeset 33556 a14a556cf2c9
parent 33555 c34ba9fa96ac
child 33557 27b563ba49e8
8141343: Subtle semantics changes for union types in cast conversion Summary: cast applied to union types do not behave correctly and sometimes pass erroneously Reviewed-by: jlahoda
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
langtools/test/tools/javac/cast/8141343/T8141343.java
langtools/test/tools/javac/cast/8141343/T8141343.out
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Wed Nov 04 12:27:00 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Thu Nov 05 11:32:01 2015 +0000
@@ -583,11 +583,13 @@
         return false;
     }
 
+    /**
+     * A compound type is a special class type whose supertypes are used to store a list
+     * of component types. There are two kinds of compound types: (i) intersection types
+     * {@see IntersectionClassType} and (ii) union types {@see UnionClassType}.
+     */
     public boolean isCompound() {
-        // Compound types can't have a (non-terminal) completer.  Calling
-        // flags() will complete the symbol causing the compiler to load
-        // classes unnecessarily.  This led to regression 6180021.
-        return tsym.isCompleted() && (tsym.flags() & COMPOUND) != 0;
+        return false;
     }
 
     public boolean isIntersection() {
@@ -1200,6 +1202,11 @@
             return true;
         }
 
+        @Override
+        public boolean isCompound() {
+            return getLub().isCompound();
+        }
+
         @Override @DefinedBy(Api.LANGUAGE_MODEL)
         public TypeKind getKind() {
             return TypeKind.UNION;
@@ -1242,6 +1249,11 @@
             return Collections.unmodifiableList(getExplicitComponents());
         }
 
+        @Override
+        public boolean isCompound() {
+            return true;
+        }
+
         public List<Type> getComponents() {
             return interfaces_field.prepend(supertype_field);
         }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Wed Nov 04 12:27:00 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Thu Nov 05 11:32:01 2015 +0000
@@ -1495,10 +1495,10 @@
                     }
                 }
 
-                if (t.isIntersection() || s.isIntersection()) {
-                    return !t.isIntersection() ?
-                            visitIntersectionType((IntersectionClassType)s, t, true) :
-                            visitIntersectionType((IntersectionClassType)t, s, false);
+                if (t.isCompound() || s.isCompound()) {
+                    return !t.isCompound() ?
+                            visitCompoundType((ClassType)s, t, true) :
+                            visitCompoundType(t, s, false);
                 }
 
                 if (s.hasTag(CLASS) || s.hasTag(ARRAY)) {
@@ -1576,9 +1576,9 @@
                 return false;
             }
 
-            boolean visitIntersectionType(IntersectionClassType ict, Type s, boolean reverse) {
+            boolean visitCompoundType(ClassType ct, Type s, boolean reverse) {
                 Warner warn = noWarnings;
-                for (Type c : ict.getComponents()) {
+                for (Type c : directSupertypes(ct)) {
                     warn.clear();
                     if (reverse ? !isCastable(s, c, warn) : !isCastable(c, s, warn))
                         return false;
@@ -2399,14 +2399,9 @@
                         ? interfaces(type)
                         : interfaces(type).prepend(sup);
                 } else {
-                    return visitIntersectionType((IntersectionClassType) type);
+                    return ((IntersectionClassType)type).getExplicitComponents();
                 }
             }
-
-            private List<Type> visitIntersectionType(final IntersectionClassType it) {
-                return it.getExplicitComponents();
-            }
-
         };
 
     public boolean isDirectSuperInterface(TypeSymbol isym, TypeSymbol origin) {
@@ -4152,7 +4147,7 @@
 
     private boolean giveWarning(Type from, Type to) {
         List<Type> bounds = to.isCompound() ?
-                ((IntersectionClassType)to).getComponents() : List.of(to);
+                directSupertypes(to) : List.of(to);
         for (Type b : bounds) {
             Type subFrom = asSub(from, b.tsym);
             if (b.isParameterized() &&
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/cast/8141343/T8141343.java	Thu Nov 05 11:32:01 2015 +0000
@@ -0,0 +1,25 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8141343
+ * @summary Subtle semantics changes for union types in cast conversion
+ * @compile/fail/ref=T8141343.out -XDrawDiagnostics T8141343.java
+ */
+
+class T8141343 {
+    interface Foo<X> { }
+
+    static class A extends Exception implements Foo<A> { }
+    static class B extends Exception implements Foo<B> { }
+
+    void test(boolean cond) {
+        try {
+            if (cond) {
+                throw new A();
+            } else {
+                throw new B();
+            }
+        } catch (A | B ex) {
+            Foo<Integer> fa = (Foo<Integer>)ex;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/cast/8141343/T8141343.out	Thu Nov 05 11:32:01 2015 +0000
@@ -0,0 +1,2 @@
+T8141343.java:22:45: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Exception&T8141343.Foo<? extends java.lang.Exception&T8141343.Foo<?>>, T8141343.Foo<java.lang.Integer>)
+1 error