private static @NotNull PsiSubstitutor composeSubstitutors(PsiSubstitutor outer, PsiSubstitutor inner, PsiClass onClass) {
    UnmodifiableHashMap<PsiTypeParameter, PsiType> answer = UnmodifiableHashMap.empty(PSI_EQUIVALENCE);
    Map<PsiTypeParameter, PsiType> outerMap = outer.getSubstitutionMap();
    Map<PsiTypeParameter, PsiType> innerMap = inner.getSubstitutionMap();
    for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(onClass)) {
      if (outerMap.containsKey(parameter) || innerMap.containsKey(parameter)) {
        PsiType innerType = inner.substitute(parameter);
        PsiClass paramCandidate = PsiCapturedWildcardType.isCapture() ? PsiUtil.resolveClassInClassTypeOnly(innerType) : null;
        PsiType targetType;
        if (paramCandidate instanceof PsiTypeParameter && paramCandidate != parameter) {
          targetType = outer.substituteWithBoundsPromotion((PsiTypeParameter)paramCandidate);
          if (targetType != null && innerType.getAnnotations().length > 0) {
            PsiAnnotation[] typeAnnotations = targetType.getAnnotations();
            targetType = targetType.annotate(() -> ArrayUtil.mergeArrays(innerType.getAnnotations(), typeAnnotations));
          }
        }
        else {
          targetType = outer.substitute(innerType);
        }
        answer = answer.with(parameter, targetType);
      }
    }
    return PsiSubstitutor.EMPTY.putAll(answer);
  }
private static @NotNull PsiSubstitutor composeSubstitutors(PsiSubstitutor outer, PsiSubstitutor inner, PsiClass onClass)