private static @NotNull PsiType narrowReturnType(@NotNull PsiType returnType, @Nullable PsiType qualifierType,
                                                   @NotNull PsiMethod realMethod) {
    PsiClass containingClass = realMethod.getContainingClass();
    PsiType realReturnType = realMethod.getReturnType();
    if (containingClass != null && qualifierType instanceof PsiClassType) {
      if (containingClass.hasTypeParameters() || containingClass.getContainingClass() != null) {
        PsiClassType.ClassResolveResult classResolveResult = ((PsiClassType)qualifierType).resolveGenerics();
        PsiClass subType = classResolveResult.getElement();
        if (subType != null && !subType.equals(containingClass)) {
          PsiSubstitutor substitutor = TypeConversionUtil
            .getMaybeSuperClassSubstitutor(containingClass, subType, classResolveResult.getSubstitutor());
          if (substitutor != null) {
            realReturnType = substitutor.substitute(realReturnType);
          }
        }
      }
    }
    if (realReturnType != null && !realReturnType.equals(returnType) &&
        TypeConversionUtil.erasure(returnType).isAssignableFrom(realReturnType)) {
      // possibly covariant return type
      return realReturnType;
    }
    return returnType;
  }
private static @NotNull PsiType narrowReturnType(@NotNull PsiType returnType, @Nullable PsiType qualifierType,
                                                   @NotNull PsiMethod realMethod)