@NotNull
  static PsiType correctTypeParameters(PsiType resultType, String superClassName, Map<String, Function<? super PsiType, ? extends PsiType>> downstreamCorrectors) {
    PsiClass resultClass = PsiUtil.resolveClassInClassTypeOnly(resultType);
    if(resultClass == null) return resultType;

    PsiSubstitutor origSubstitutor = ((PsiClassType)resultType).resolveGenerics().getSubstitutor();
    PsiSubstitutor substitutor = origSubstitutor;
    Project project = resultClass.getProject();
    PsiClass superClass = JavaPsiFacade.getInstance(project).findClass(superClassName, resultClass.getResolveScope());
    if(superClass == null) return resultType;
    PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getMaybeSuperClassSubstitutor(superClass, resultClass, PsiSubstitutor.EMPTY);
    if(superClassSubstitutor == null) {
      // inconsistent class hierarchy: probably something is not resolved
      return resultType;
    }
    for (PsiTypeParameter baseParameter : superClass.getTypeParameters()) {
      PsiClass substitution = PsiUtil.resolveClassInClassTypeOnly(superClassSubstitutor.substitute(baseParameter));
      if(substitution instanceof PsiTypeParameter subClassParameter) {
        PsiType origType = origSubstitutor.substitute(subClassParameter);
        PsiType replacedType = GenericsUtil.eliminateWildcards(origType, false, true);
        replacedType = downstreamCorrectors.getOrDefault(subClassParameter.getName(), Function.identity()).apply(replacedType);
        if(replacedType != origType) {
          substitutor = substitutor.put(subClassParameter, replacedType);
        }
      }
    }
    return substitutor == origSubstitutor ? resultType : JavaPsiFacade.getElementFactory(project).createType(resultClass, substitutor);
  }
@NotNull
  static PsiType correctTypeParameters(PsiType resultType, String superClassName, Map<String, Function<? super PsiType, ? extends PsiType>> downstreamCorrectors)