private PsiType composeBound(InferenceVariable variable,
                               InferenceBound boundType,
                               Function<? super Pair<PsiType, PsiType>, ? extends PsiType> fun,
                               PsiSubstitutor substitutor,
                               boolean includeNonProperBounds) {
    final List<PsiType> bounds = variable.getBounds(boundType);
    PsiType lub = PsiTypes.nullType();
    for (PsiType bound : bounds) {
      bound = substituteNonProperBound(bound, substitutor);
      if (includeNonProperBounds || isProperType(bound)) {
        if (lub == PsiTypes.nullType()) {
          lub = bound;
        }
        else {
          final Pair<PsiType, PsiType> pair = Pair.create(lub, bound);
          lub = fun.fun(pair);
          if (lub == null) {
            return PsiTypes.nullType();
          }
        }
      }
    }
    return lub;
  }
private PsiType composeBound(InferenceVariable variable,
                               InferenceBound boundType,
                               Function<? super Pair<PsiType, PsiType>, ? extends PsiType> fun,
                               PsiSubstitutor substitutor,
                               boolean includeNonProperBounds)