@@ -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 () {
0 commit comments