private static PsiSubstitutor processLowerBound(@NotNull PsiType lowerBound,
                                                  @NotNull PsiClass derivedClass,
                                                  @NotNull GlobalSearchScope scope,
                                                  @NotNull PsiSubstitutor derivedSubstitutor) {
    if (lowerBound instanceof PsiClassType) {
      final PsiClassType.ClassResolveResult result = ((PsiClassType)lowerBound).resolveGenerics();
      final PsiClass boundClass = result.getElement();
      if (boundClass != null) {
        if (boundClass.equals(derivedClass)) {
          return derivedSubstitutor;
        }
        final PsiSubstitutor substitutor = getSuperSubstitutorWithCaching(boundClass,
                                                                          derivedClass, scope, result.getSubstitutor());
        if (substitutor != null) {
          return composeSubstitutors(derivedSubstitutor, substitutor, boundClass);
        }
      }
    }
    else if (lowerBound instanceof PsiIntersectionType) {
      for (PsiType bound : ((PsiIntersectionType)lowerBound).getConjuncts()) {
        final PsiSubstitutor substitutor = processLowerBound(bound, derivedClass, scope, derivedSubstitutor);
        if (substitutor != null) {
          return substitutor;
        }
      }
    }
    else if (lowerBound instanceof PsiCapturedWildcardType) {
      return processLowerBound(((PsiCapturedWildcardType)lowerBound).getUpperBound(), derivedClass, scope, derivedSubstitutor);
    }
    return null;
  }
private static PsiSubstitutor processLowerBound(@NotNull PsiType lowerBound,
                                                  @NotNull PsiClass derivedClass,
                                                  @NotNull GlobalSearchScope scope,
                                                  @NotNull PsiSubstitutor derivedSubstitutor)