Skip to content

Commit 1f09467

Browse files
committed
8327368: javac crash when computing exhaustiveness checks
Reviewed-by: vromero
1 parent 7dbd033 commit 1f09467

File tree

2 files changed

+98
-7
lines changed

2 files changed

+98
-7
lines changed

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -937,7 +937,7 @@ private Set<PatternDescription> reduceBindingPatterns(Type selectorType, Set<Pat
937937
for (PatternDescription pdOther : patterns) {
938938
if (pdOther instanceof BindingPattern bpOther) {
939939
Set<Symbol> currentPermittedSubTypes =
940-
allPermittedSubTypes((ClassSymbol) bpOther.type.tsym, s -> true);
940+
allPermittedSubTypes(bpOther.type.tsym, s -> true);
941941

942942
PERMITTED: for (Iterator<Symbol> it = permitted.iterator(); it.hasNext();) {
943943
Symbol perm = it.next();
@@ -973,9 +973,9 @@ private Set<PatternDescription> reduceBindingPatterns(Type selectorType, Set<Pat
973973
return patterns;
974974
}
975975

976-
private Set<Symbol> allPermittedSubTypes(ClassSymbol root, Predicate<ClassSymbol> accept) {
976+
private Set<Symbol> allPermittedSubTypes(TypeSymbol root, Predicate<ClassSymbol> accept) {
977977
Set<Symbol> permitted = new HashSet<>();
978-
List<ClassSymbol> permittedSubtypesClosure = List.of(root);
978+
List<ClassSymbol> permittedSubtypesClosure = baseClasses(root);
979979

980980
while (permittedSubtypesClosure.nonEmpty()) {
981981
ClassSymbol current = permittedSubtypesClosure.head;
@@ -999,6 +999,20 @@ private Set<Symbol> allPermittedSubTypes(ClassSymbol root, Predicate<ClassSymbol
999999
return permitted;
10001000
}
10011001

1002+
private List<ClassSymbol> baseClasses(TypeSymbol root) {
1003+
if (root instanceof ClassSymbol clazz) {
1004+
return List.of(clazz);
1005+
} else if (root instanceof TypeVariableSymbol tvar) {
1006+
ListBuffer<ClassSymbol> result = new ListBuffer<>();
1007+
for (Type bound : tvar.getBounds()) {
1008+
result.appendList(baseClasses(bound.tsym));
1009+
}
1010+
return result.toList();
1011+
} else {
1012+
return List.nil();
1013+
}
1014+
}
1015+
10021016
/* Among the set of patterns, find sub-set of patterns such:
10031017
* $record($prefix$, $nested, $suffix$)
10041018
* Where $record, $prefix$ and $suffix$ is the same for each pattern
@@ -1144,7 +1158,7 @@ private PatternDescription reduceRecordPattern(PatternDescription pattern) {
11441158
reducedNestedPatterns[i] = newNested;
11451159
}
11461160

1147-
covered &= isBpCovered(componentType[i], newNested);
1161+
covered &= checkCovered(componentType[i], List.of(newNested));
11481162
}
11491163
if (covered) {
11501164
return new BindingPattern(rpOne.recordType);
@@ -1175,7 +1189,7 @@ private Set<PatternDescription> expandGenericPatterns(Set<PatternDescription> pa
11751189
}
11761190
}
11771191
} else if (pd instanceof BindingPattern bp) {
1178-
Set<Symbol> permittedSymbols = allPermittedSubTypes((ClassSymbol) bp.type.tsym, cs -> true);
1192+
Set<Symbol> permittedSymbols = allPermittedSubTypes(bp.type.tsym, cs -> true);
11791193

11801194
if (!permittedSymbols.isEmpty()) {
11811195
for (Symbol permitted : permittedSymbols) {

test/langtools/tools/javac/patterns/Exhaustiveness.java

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
2323

2424
/**
2525
* @test
26-
* @bug 8262891 8268871 8274363 8281100 8294670 8311038 8311815 8325215 8333169
26+
* @bug 8262891 8268871 8274363 8281100 8294670 8311038 8311815 8325215 8333169 8327368
2727
* @summary Check exhaustiveness of switches over sealed types.
2828
* @library /tools/lib
2929
* @modules jdk.compiler/com.sun.tools.javac.api
@@ -2105,6 +2105,83 @@ static <T> T log(T t) {
21052105
}""");
21062106
}
21072107

2108+
@Test
2109+
public void testNestedIntersectionType(Path base) throws Exception {
2110+
doTest(base,
2111+
new String[0],
2112+
"""
2113+
public class Test {
2114+
2115+
static abstract class Abs {}
2116+
2117+
sealed interface B permits V {}
2118+
2119+
static final class V extends Abs implements B {}
2120+
2121+
final static record R<T extends B>(T b) {}
2122+
2123+
static <T extends Abs & B> int r(R<T> r) {
2124+
return switch (r) {
2125+
case R(B b) -> 3;
2126+
};
2127+
}
2128+
}
2129+
""");
2130+
}
2131+
@Test //JDK-8327368
2132+
public void testExpandForTypeVariables(Path base) throws Exception {
2133+
doTest(base,
2134+
new String[0],
2135+
"""
2136+
public class Test {
2137+
sealed interface A permits T, U {}
2138+
sealed interface B permits V, W {}
2139+
2140+
static final class T implements A { public T() {} }
2141+
static final class U implements A { public U() {} }
2142+
2143+
static final class V implements B { public V() {} }
2144+
static final class W implements B { public W() {} }
2145+
2146+
final static record R<T1 extends A, T2 extends B>(T1 a, T2 b) { }
2147+
2148+
static <T1 extends A, T2 extends B> int r(R<T1, T2> r) {
2149+
return switch (r) {
2150+
case R(A a, V b) -> 1; // Any A with specific B
2151+
case R(T a, var b) -> 2; // Specific A with any B
2152+
case R(U a, W b) -> 3; // Specific A with specific B
2153+
};
2154+
}
2155+
}
2156+
""");
2157+
doTest(base,
2158+
new String[0],
2159+
"""
2160+
public class Test {
2161+
sealed interface A permits T, U {}
2162+
sealed interface B permits V, W {}
2163+
2164+
static final class T implements A { public T() {} }
2165+
static final class U implements A { public U() {} }
2166+
2167+
static final class V extends Abs implements B { public V() {} }
2168+
static final class W extends Abs implements B { public W() {} }
2169+
2170+
static abstract class Abs {}
2171+
2172+
final static record R<T1 extends A, T2 extends B>(T1 a, T2 b) { }
2173+
2174+
static <T1 extends A, T2 extends Abs & B> int r(R<T1, T2> r) {
2175+
return switch (r) {
2176+
case R(A a, V b) -> 1; // Any A with specific B
2177+
case R(T a, var b) -> 2; // Specific A with any B
2178+
case R(U a, W b) -> 3; // Specific A with specific B
2179+
};
2180+
}
2181+
}
2182+
""");
2183+
}
2184+
21082185
private void doTest(Path base, String[] libraryCode, String testCode, String... expectedErrors) throws IOException {
21092186
doTest(base, libraryCode, testCode, false, expectedErrors);
21102187
}

0 commit comments

Comments
 (0)