8141343: Subtle semantics changes for union types in cast conversion
Cast applied to union types do not behave correctly and sometimes pass erroneously Reviewed-by: jlahoda
This commit is contained in:
parent
d2d6dd48d4
commit
a65f240258
langtools
src/jdk.compiler/share/classes/com/sun/tools/javac/code
test/tools/javac/cast/8141343
@ -583,11 +583,13 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
||||
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 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompound() {
|
||||
return getLub().isCompound();
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.LANGUAGE_MODEL)
|
||||
public TypeKind getKind() {
|
||||
return TypeKind.UNION;
|
||||
@ -1242,6 +1249,11 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
||||
return Collections.unmodifiableList(getExplicitComponents());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompound() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<Type> getComponents() {
|
||||
return interfaces_field.prepend(supertype_field);
|
||||
}
|
||||
|
@ -1495,10 +1495,10 @@ public class Types {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public class Types {
|
||||
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 @@ public class Types {
|
||||
? 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 @@ public class Types {
|
||||
|
||||
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() &&
|
||||
|
25
langtools/test/tools/javac/cast/8141343/T8141343.java
Normal file
25
langtools/test/tools/javac/cast/8141343/T8141343.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
2
langtools/test/tools/javac/cast/8141343/T8141343.out
Normal file
2
langtools/test/tools/javac/cast/8141343/T8141343.out
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user