PsiClass (List<? extends PsiType> upperBounds, Processor<? super Pair<PsiType, PsiType>> processor) { for (int i = 0; i < upperBounds.size(); i++) { final PsiType sBound = upperBounds.get(i); final PsiClass sClass = PsiUtil.resolveClassInClassTypeOnly(sBound); if (sClass == null) continue; final LinkedHashSet<PsiClass> superClasses = InheritanceUtil.getSuperClasses(sClass); superClasses.add(sClass); for (int j = i + 1; j < upperBounds.size(); j++) { final PsiType tBound = upperBounds.get(j); final PsiClass tClass = PsiUtil.resolveClassInClassTypeOnly(tBound); if (tClass != null) { final LinkedHashSet<PsiClass> tSupers = new LinkedHashSet<>(); tSupers.add(tClass); tSupers.addAll(InheritanceUtil.getSuperClasses(tClass)); tSupers.retainAll(superClasses); for (PsiClass gClass : tSupers) { final PsiSubstitutor sSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(gClass, (PsiClassType)sBound); final PsiSubstitutor tSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(gClass, (PsiClassType)tBound); boolean found = false; for (PsiTypeParameter typeParameter : gClass.getTypeParameters()) { final PsiType sType = sSubstitutor.substituteWithBoundsPromotion(typeParameter); final PsiType tType = tSubstitutor.substituteWithBoundsPromotion(typeParameter); final Pair<PsiType, PsiType> typePair = Pair.create(sType, tType); if (!processor.process(typePair)) { found = true; } } if (found) return gClass; } } } } return null; }