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
--- 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