diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
index 9de7a6292db67..737672afbc125 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
@@ -815,6 +815,7 @@ private boolean exhausts(JCExpression selector, List<JCCase> cases) {
                 }
             }
             Set<PatternDescription> patterns = patternSet;
+            boolean genericPatternsExpanded = false;
             try {
                 boolean repeat = true;
                 while (repeat) {
@@ -824,10 +825,22 @@ private boolean exhausts(JCExpression selector, List<JCCase> cases) {
                     updatedPatterns = reduceRecordPatterns(updatedPatterns);
                     updatedPatterns = removeCoveredRecordPatterns(updatedPatterns);
                     repeat = !updatedPatterns.equals(patterns);
-                    patterns = updatedPatterns;
                     if (checkCovered(selector.type, patterns)) {
                         return true;
                     }
+                    if (!repeat && !genericPatternsExpanded) {
+                        //there may be situation like:
+                        //class B extends S1, S2
+                        //patterns: R(S1, B), R(S2, S2)
+                        //this should be joined to R(B, S2),
+                        //but hashing in reduceNestedPatterns will not allow that
+                        //attempt to once expand all types to their transitive permitted types,
+                        //on all depth of nesting:
+                        updatedPatterns = expandGenericPatterns(updatedPatterns);
+                        genericPatternsExpanded = true;
+                        repeat = !updatedPatterns.equals(patterns);
+                    }
+                    patterns = updatedPatterns;
                 }
                 return checkCovered(selector.type, patterns);
             } catch (CompletionFailure cf) {
@@ -1130,6 +1143,40 @@ private PatternDescription reduceRecordPattern(PatternDescription pattern) {
             return pattern;
         }
 
+        private Set<PatternDescription> expandGenericPatterns(Set<PatternDescription> patterns) {
+            var newPatterns = new HashSet<PatternDescription>(patterns);
+            boolean modified;
+            do {
+                modified = false;
+                for (PatternDescription pd : patterns) {
+                    if (pd instanceof RecordPattern rpOne) {
+                        for (int i = 0; i < rpOne.nested.length; i++) {
+                            Set<PatternDescription> toExpand = Set.of(rpOne.nested[i]);
+                            Set<PatternDescription> expanded = expandGenericPatterns(toExpand);
+                            if (expanded != toExpand) {
+                                expanded.removeAll(toExpand);
+                                for (PatternDescription exp : expanded) {
+                                    PatternDescription[] newNested = Arrays.copyOf(rpOne.nested, rpOne.nested.length);
+                                    newNested[i] = exp;
+                                    modified |= newPatterns.add(new RecordPattern(rpOne.recordType(), rpOne.fullComponentTypes(), newNested));
+                                }
+                            }
+                        }
+                    } else if (pd instanceof BindingPattern bp) {
+                        Set<Symbol> permittedSymbols = allPermittedSubTypes((ClassSymbol) bp.type.tsym, cs -> true);
+
+                        if (!permittedSymbols.isEmpty()) {
+                            for (Symbol permitted : permittedSymbols) {
+                                //TODO infer.instantiatePatternType(selectorType, csym); (?)
+                                modified |= newPatterns.add(new BindingPattern(permitted.type));
+                            }
+                        }
+                    }
+                }
+            } while (modified);
+            return newPatterns;
+        }
+
         private Set<PatternDescription> removeCoveredRecordPatterns(Set<PatternDescription> patterns) {
             Set<Symbol> existingBindings = patterns.stream()
                                                    .filter(pd -> pd instanceof BindingPattern)
diff --git a/test/langtools/tools/javac/patterns/Exhaustiveness.java b/test/langtools/tools/javac/patterns/Exhaustiveness.java
index dad1a0c86f8d7..726bd1d9a2e9a 100644
--- a/test/langtools/tools/javac/patterns/Exhaustiveness.java
+++ b/test/langtools/tools/javac/patterns/Exhaustiveness.java
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 8262891 8268871 8274363 8281100 8294670 8311038 8311815
+ * @bug 8262891 8268871 8274363 8281100 8294670 8311038 8311815 8325215
  * @summary Check exhaustiveness of switches over sealed types.
  * @library /tools/lib
  * @modules jdk.compiler/com.sun.tools.javac.api
@@ -1996,6 +1996,86 @@ case Pair(D fst, D snd) -> {
                """);
     }
 
+    @Test //JDK-8325215:
+    public void testTooGenericPatternInRecord(Path base) throws Exception {
+        doTest(base,
+               new String[0],
+               """
+               package test;
+               public class Test {
+                   sealed interface A permits T, U {}
+                   sealed interface B permits V, W {}
+
+                   static final class T implements A { public T() {} }
+                   static final class U implements A { public U() {} }
+
+                   static final class V implements B { public V() {} }
+                   static final class W implements B { public W() {} }
+
+                   final static record R(A a, B b) { }
+
+                   static int r(R r) {
+                      return switch (r) {
+                          case R(A a, V b) -> 1; // Any A with specific B
+                          case R(T a, B b) -> 2; // Specific A with any B
+                          case R(U a, W b) -> 3; // Specific A with specific B
+                      };
+                   }
+               }
+               """);
+        doTest(base,
+               new String[0],
+               """
+               package test;
+               public class Test {
+                   sealed interface A permits T, U {}
+                   sealed interface B permits V, W {}
+
+                   static final class T implements A { public T() {} }
+                   static final class U implements A { public U() {} }
+
+                   static final class V implements B { public V() {} }
+                   static final class W implements B { public W() {} }
+
+                   final static record R(B b, A a) { }
+
+                   static int r(R r) {
+                      return switch (r) {
+                          case R(V b, A a) -> 1; // Any A with specific B
+                          case R(B b, T a) -> 2; // Specific A with any B
+                          case R(W b, U a) -> 3; // Specific A with specific B
+                      };
+                   }
+               }
+               """);
+        doTest(base,
+               new String[0],
+               """
+               package test;
+               public class Test {
+                   sealed interface A permits T, U {}
+                   sealed interface B permits V, W {}
+
+                   static final class T implements A { public T() {} }
+                   static final class U implements A { public U() {} }
+
+                   static final class V implements B { public V() {} }
+                   static final class W implements B { public W() {} }
+
+                   final static record X(B b) { }
+                   final static record R(A a, X x) { }
+
+                   static int r(R r) {
+                      return switch (r) {
+                          case R(A a, X(V b)) -> 1; // Any A with specific B
+                          case R(T a, X(B b)) -> 2; // Specific A with any B
+                          case R(U a, X(W b)) -> 3; // Specific A with specific B
+                      };
+                   }
+               }
+               """);
+    }
+
     private void doTest(Path base, String[] libraryCode, String testCode, String... expectedErrors) throws IOException {
         doTest(base, libraryCode, testCode, false, expectedErrors);
     }