Skip to content
Permalink
Browse files
8274363: Transitively sealed classes not considered exhaustive in swi…
…tches

Reviewed-by: vromero
  • Loading branch information
Jan Lahoda committed Oct 1, 2021
1 parent 1887028 commit 292d7bb1d5d311b517b2cd6d0f6dc77e35b3f649
Showing with 64 additions and 18 deletions.
  1. +25 −6 src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
  2. +39 −12 test/langtools/tools/javac/patterns/Exhaustiveness.java
@@ -207,6 +207,7 @@
private final JCDiagnostic.Factory diags;
private Env<AttrContext> attrEnv;
private Lint lint;
private final DeferredCompletionFailureHandler dcfh;
private final boolean allowEffectivelyFinalInInnerClasses;

public static Flow instance(Context context) {
@@ -331,6 +332,7 @@ protected Flow(Context context) {
lint = Lint.instance(context);
rs = Resolve.instance(context);
diags = JCDiagnostic.Factory.instance(context);
dcfh = DeferredCompletionFailureHandler.instance(context);
Source source = Source.instance(context);
allowEffectivelyFinalInInnerClasses = Feature.EFFECTIVELY_FINAL_IN_INNER_CLASSES.allowedInSource(source);
}
@@ -770,12 +772,9 @@ private void transitiveCovers(Set<Symbol> covered) {

case TYP -> {
for (Type sup : types.directSupertypes(sym.type)) {
if (sup.tsym.kind == TYP && sup.tsym.isAbstract() && sup.tsym.isSealed()) {
boolean hasAll = ((ClassSymbol) sup.tsym).permitted
.stream()
.allMatch(covered::contains);

if (hasAll && covered.add(sup.tsym)) {
if (sup.tsym.kind == TYP) {
if (isTransitivelyCovered(sup.tsym, covered) &&
covered.add(sup.tsym)) {
todo = todo.prepend(sup.tsym);
}
}
@@ -785,6 +784,26 @@ private void transitiveCovers(Set<Symbol> covered) {
}
}

private boolean isTransitivelyCovered(Symbol sealed, Set<Symbol> covered) {
DeferredCompletionFailureHandler.Handler prevHandler =
dcfh.setHandler(dcfh.speculativeCodeHandler);
try {
if (covered.stream().anyMatch(c -> sealed.isSubClass(c, types)))
return true;
if (sealed.kind == TYP && sealed.isAbstract() && sealed.isSealed()) {
return ((ClassSymbol) sealed).permitted
.stream()
.allMatch(s -> isTransitivelyCovered(s, covered));
}
return false;
} catch (CompletionFailure cf) {
//safe to ignore, the symbol will be un-completed when the speculative handler is removed.
return false;
} finally {
dcfh.setHandler(prevHandler);
}
}

private boolean isExhaustive(Type seltype, Set<Symbol> covered) {
transitiveCovers(covered);
return switch (seltype.getTag()) {
@@ -23,7 +23,7 @@

/**
* @test
* @bug 8262891 8268871
* @bug 8262891 8268871 8274363
* @summary Check exhaustiveness of switches over sealed types.
* @library /tools/lib
* @modules jdk.compiler/com.sun.tools.javac.api
@@ -775,23 +775,50 @@ public void testNotExhaustiveIntersection(Path base) throws Exception {
"1 error");
}

@Test
public void testTransitiveSealed(Path base) throws Exception {
doTest(base,
new String[0],
"""
package test;
public class Test {
sealed interface A {}
sealed interface B1 extends A {}
sealed interface B2 extends A {}
sealed interface C extends A {}
final class D1 implements B1, C {}
final class D2 implements B2, C {}
void test(A arg) {
int i = switch (arg) {
case B1 b1 -> 1;
case B2 b2 -> 2;
};
}
}
""");
}

private void doTest(Path base, String[] libraryCode, String testCode, String... expectedErrors) throws IOException {
Path current = base.resolve(".");
Path libSrc = current.resolve("lib-src");
for (String code : libraryCode) {
tb.writeJavaFiles(libSrc, code);
}

Path libClasses = current.resolve("libClasses");

Files.createDirectories(libClasses);

new JavacTask(tb)
.options("--enable-preview",
"-source", JAVA_VERSION)
.outdir(libClasses)
.files(tb.findJavaFiles(libSrc))
.run();
if (libraryCode.length != 0) {
Path libSrc = current.resolve("lib-src");

for (String code : libraryCode) {
tb.writeJavaFiles(libSrc, code);
}

new JavacTask(tb)
.options("--enable-preview",
"-source", JAVA_VERSION)
.outdir(libClasses)
.files(tb.findJavaFiles(libSrc))
.run();
}

Path src = current.resolve("src");
tb.writeJavaFiles(src, testCode);

1 comment on commit 292d7bb

@openjdk-notifier

This comment has been minimized.

Copy link

@openjdk-notifier openjdk-notifier bot commented on 292d7bb Oct 1, 2021

Please sign in to comment.