@Override
  public @Nullable PsiSubstitutor getSuperClassSubstitutor(@NotNull PsiClass superClass,
                                                           @NotNull PsiClass derivedClass,
                                                           @NotNull GlobalSearchScope scope,
                                                           @NotNull PsiSubstitutor derivedSubstitutor) {
    if (InheritanceImplUtil.hasObjectQualifiedName(superClass)) return PsiSubstitutor.EMPTY;
    List<PsiType> bounds = null;
    if (superClass instanceof InferenceVariable) {
      bounds = ((InferenceVariable)superClass).getBounds(InferenceBound.LOWER);
    }
    else if (superClass instanceof PsiTypeParameter) {
      final PsiType lowerBound = TypeConversionUtil.getInferredLowerBoundForSynthetic((PsiTypeParameter)superClass);
      if (lowerBound != null) {
        bounds = Collections.singletonList(lowerBound);
      }
    }
    if (bounds != null) {
      for (PsiType lowerBound : bounds) {
        if (lowerBound != null) {
          final PsiSubstitutor substitutor = processLowerBound(lowerBound, derivedClass, scope, derivedSubstitutor);
          if (substitutor != null) {
            return substitutor;
          }
        }
      }
    }

    return derivedClass instanceof PsiTypeParameter
           ? processTypeParameter((PsiTypeParameter)derivedClass, scope, superClass, new HashSet<>(), derivedSubstitutor)
           : getSuperSubstitutorWithCaching(superClass, derivedClass, scope, derivedSubstitutor);
  }
@Override
  public @Nullable PsiSubstitutor getSuperClassSubstitutor(@NotNull PsiClass superClass,
                                                           @NotNull PsiClass derivedClass,
                                                           @NotNull GlobalSearchScope scope,
                                                           @NotNull PsiSubstitutor derivedSubstitutor)