boolean (@NotNull PsiClass leftClass, @NotNull PsiClass rightClass, @NotNull PsiSubstitutor leftSubstitutor, @NotNull PsiSubstitutor rightSubstitutor, @NotNull PsiElement context) { if (!leftClass.hasTypeParameters()) return true; if (!leftClass.getManager().areElementsEquivalent(leftClass, rightClass)) { rightSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(leftClass, rightClass, rightSubstitutor); rightClass = leftClass; } else if (!rightClass.hasTypeParameters()) return true; Iterator<PsiTypeParameter> li = PsiUtil.typeParametersIterator(leftClass); Iterator<PsiTypeParameter> ri = PsiUtil.typeParametersIterator(rightClass); while (li.hasNext()) { if (!ri.hasNext()) return false; PsiTypeParameter lp = li.next(); PsiTypeParameter rp = ri.next(); final PsiType typeLeft = leftSubstitutor.substitute(lp); if (typeLeft == null) continue; final PsiType typeRight = rightSubstitutor.substituteWithBoundsPromotion(rp); if (typeRight == null) { // compatibility feature: allow to assign raw types to generic ones return true; } if (typeLeft instanceof PsiClassType && typeRight instanceof PsiClassType) { if (!TypesUtil.isAssignableByMethodCallConversion(typeLeft, typeRight, context)) { return false; } } else if (!TypeConversionUtil.typesAgree(typeLeft, typeRight, true)) { return false; } } return true; }