Skip to content

Commit 8345043

Browse files
Vicente Romeropull[bot]
authored andcommitted
8319987: compilation of sealed classes leads to infinite recursion
Reviewed-by: jlahoda
1 parent 58b8591 commit 8345043

File tree

3 files changed

+49
-25
lines changed

3 files changed

+49
-25
lines changed

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,37 +1665,46 @@ public boolean isCastable(Type t, Type s, Warner warn) {
16651665
&& (t.tsym.isSealed() || s.tsym.isSealed())) {
16661666
return (t.isCompound() || s.isCompound()) ?
16671667
true :
1668-
!areDisjoint((ClassSymbol)t.tsym, (ClassSymbol)s.tsym);
1668+
!(new DisjointChecker().areDisjoint((ClassSymbol)t.tsym, (ClassSymbol)s.tsym));
16691669
}
16701670
return result;
16711671
}
16721672
// where
1673-
private boolean areDisjoint(ClassSymbol ts, ClassSymbol ss) {
1674-
if (isSubtype(erasure(ts.type), erasure(ss.type))) {
1675-
return false;
1676-
}
1677-
// if both are classes or both are interfaces, shortcut
1678-
if (ts.isInterface() == ss.isInterface() && isSubtype(erasure(ss.type), erasure(ts.type))) {
1679-
return false;
1680-
}
1681-
if (ts.isInterface() && !ss.isInterface()) {
1682-
/* so ts is interface but ss is a class
1683-
* an interface is disjoint from a class if the class is disjoint form the interface
1673+
class DisjointChecker {
1674+
Set<Pair<ClassSymbol, ClassSymbol>> pairsSeen = new HashSet<>();
1675+
private boolean areDisjoint(ClassSymbol ts, ClassSymbol ss) {
1676+
Pair<ClassSymbol, ClassSymbol> newPair = new Pair<>(ts, ss);
1677+
/* if we are seeing the same pair again then there is an issue with the sealed hierarchy
1678+
* bail out, a detailed error will be reported downstream
16841679
*/
1685-
return areDisjoint(ss, ts);
1686-
}
1687-
// a final class that is not subtype of ss is disjoint
1688-
if (!ts.isInterface() && ts.isFinal()) {
1689-
return true;
1690-
}
1691-
// if at least one is sealed
1692-
if (ts.isSealed() || ss.isSealed()) {
1693-
// permitted subtypes have to be disjoint with the other symbol
1694-
ClassSymbol sealedOne = ts.isSealed() ? ts : ss;
1695-
ClassSymbol other = sealedOne == ts ? ss : ts;
1696-
return sealedOne.permitted.stream().allMatch(sym -> areDisjoint((ClassSymbol)sym, other));
1680+
if (!pairsSeen.add(newPair))
1681+
return false;
1682+
if (isSubtype(erasure(ts.type), erasure(ss.type))) {
1683+
return false;
1684+
}
1685+
// if both are classes or both are interfaces, shortcut
1686+
if (ts.isInterface() == ss.isInterface() && isSubtype(erasure(ss.type), erasure(ts.type))) {
1687+
return false;
1688+
}
1689+
if (ts.isInterface() && !ss.isInterface()) {
1690+
/* so ts is interface but ss is a class
1691+
* an interface is disjoint from a class if the class is disjoint form the interface
1692+
*/
1693+
return areDisjoint(ss, ts);
1694+
}
1695+
// a final class that is not subtype of ss is disjoint
1696+
if (!ts.isInterface() && ts.isFinal()) {
1697+
return true;
1698+
}
1699+
// if at least one is sealed
1700+
if (ts.isSealed() || ss.isSealed()) {
1701+
// permitted subtypes have to be disjoint with the other symbol
1702+
ClassSymbol sealedOne = ts.isSealed() ? ts : ss;
1703+
ClassSymbol other = sealedOne == ts ? ss : ts;
1704+
return sealedOne.permitted.stream().allMatch(sym -> areDisjoint((ClassSymbol)sym, other));
1705+
}
1706+
return false;
16971707
}
1698-
return false;
16991708
}
17001709

17011710
private TypeRelation isCastable = new TypeRelation() {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* @test /nodynamiccopyright/
3+
* @bug 8319987
4+
* @summary compilation of sealed classes leads to infinite recursion
5+
* @compile/fail/ref=CyclicHierarchyTest.out -XDrawDiagnostics CyclicHierarchyTest.java
6+
*/
7+
8+
class CyclicHierarchyTest {
9+
sealed interface Action permits Add {}
10+
sealed interface MathOp permits Add {}
11+
sealed static class Add implements MathOp permits Add {}
12+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CyclicHierarchyTest.java:9:37: compiler.err.invalid.permits.clause: (compiler.misc.doesnt.extend.sealed: CyclicHierarchyTest.Add)
2+
CyclicHierarchyTest.java:11:55: compiler.err.invalid.permits.clause: (compiler.misc.must.not.be.same.class)
3+
2 errors

0 commit comments

Comments
 (0)