private Match patternsMatch(@Nullable PsiPattern pattern1, @Nullable PsiPattern pattern2) {
    if (pattern1 == pattern2) {
      return EXACT_MATCH;
    }
    if (pattern1 == null || pattern2 == null) {
      return EXACT_MISMATCH;
    }
    if (pattern1 instanceof PsiUnnamedPattern && pattern2 instanceof PsiUnnamedPattern) {
      return EXACT_MATCH;
    }
    if (pattern1 instanceof PsiTypeTestPattern && pattern2 instanceof PsiTypeTestPattern) {
      return Match.exact(primaryPatternsMatch((PsiTypeTestPattern)pattern1, (PsiTypeTestPattern)pattern2));
    }
    if (pattern1 instanceof PsiDeconstructionPattern deconstruction1 && pattern2 instanceof PsiDeconstructionPattern deconstruction2) {
      PsiPattern[] components1 = deconstruction1.getDeconstructionList().getDeconstructionComponents();
      PsiPattern[] components2 = deconstruction2.getDeconstructionList().getDeconstructionComponents();
      if (components1.length != components2.length) {
        return EXACT_MISMATCH;
      }
      for (int i = 0; i < components1.length; i++) {
        if (!patternsMatch(components1[i], components2[i]).isExactMatch()) {
          return EXACT_MISMATCH;
        }
      }
      PsiPatternVariable variable1 = deconstruction1.getPatternVariable();
      PsiPatternVariable variable2 = deconstruction2.getPatternVariable();
      if ((variable1 == null || variable2 == null) && !Match.exact(variable1 == variable2).isExactMatch()) {
        return EXACT_MISMATCH;
      }
      PsiTypeElement typeElement1 = deconstruction1.getTypeElement();
      PsiTypeElement typeElement2 = deconstruction2.getTypeElement();
      if (!typeElementsAreEquivalent(typeElement1, typeElement2).isExactMatch()) {
        return EXACT_MISMATCH;
      }
      markDeclarationsAsEquivalent(variable1, variable2);
      return EXACT_MATCH;
    }
    return EXACT_MISMATCH;
  }
private Match patternsMatch(@Nullable PsiPattern pattern1, @Nullable PsiPattern pattern2)