private void resolveUpperBoundsFromWhereClause(Set<JetType> upperBounds) {
    JetClassOrObject classOrObject =
        JetStubbedPsiUtil.getPsiOrStubParent(jetTypeParameter, JetClassOrObject.class, true);
    if (classOrObject instanceof JetClass) {
      JetClass jetClass = (JetClass) classOrObject;
      for (JetTypeConstraint jetTypeConstraint : jetClass.getTypeConstraints()) {
        DescriptorResolver.reportUnsupportedClassObjectConstraint(
            resolveSession.getTrace(), jetTypeConstraint);

        JetSimpleNameExpression constrainedParameterName =
            jetTypeConstraint.getSubjectTypeParameterName();
        if (constrainedParameterName != null) {
          if (getName().equals(constrainedParameterName.getReferencedNameAsName())) {
            resolveSession
                .getTrace()
                .record(BindingContext.REFERENCE_TARGET, constrainedParameterName, this);

            JetTypeReference boundTypeReference = jetTypeConstraint.getBoundTypeReference();
            if (boundTypeReference != null) {
              JetType boundType = resolveBoundType(boundTypeReference);
              if (!jetTypeConstraint.isClassObjectConstraint()) {
                upperBounds.add(boundType);
              }
            }
          }
        }
      }
    }
  }
  private void checkTypesInClassHeader(@NotNull JetClassOrObject classOrObject) {
    for (JetDelegationSpecifier delegationSpecifier : classOrObject.getDelegationSpecifiers()) {
      checkBoundsForTypeInClassHeader(delegationSpecifier.getTypeReference());
    }

    if (!(classOrObject instanceof JetClass)) return;
    JetClass jetClass = (JetClass) classOrObject;

    for (JetTypeParameter jetTypeParameter : jetClass.getTypeParameters()) {
      checkBoundsForTypeInClassHeader(jetTypeParameter.getExtendsBound());
      checkFinalUpperBounds(jetTypeParameter.getExtendsBound());
    }

    for (JetTypeConstraint constraint : jetClass.getTypeConstraints()) {
      checkBoundsForTypeInClassHeader(constraint.getBoundTypeReference());
      checkFinalUpperBounds(constraint.getBoundTypeReference());
    }
  }
 @Nullable
 private static JetTypeConstraint findTypeParameterConstraint(
     @NotNull JetFunction function, @NotNull Name typeParameterName, int index) {
   if (index != 0) {
     int currentIndex = 0;
     for (JetTypeConstraint constraint : function.getTypeConstraints()) {
       JetSimpleNameExpression parameterName = constraint.getSubjectTypeParameterName();
       assert parameterName != null;
       if (typeParameterName.equals(parameterName.getReferencedNameAsName())) {
         currentIndex++;
       }
       if (currentIndex == index) {
         return constraint;
       }
     }
   }
   return null;
 }
  private void computeTypeParameters(List<TypeParameterDescriptor> typeParameters) {
    if (typeParameters.size() != altFunDeclaration.getTypeParameters().size()) {
      throw new AlternativeSignatureMismatchException(
          "Method signature has %d type parameters, but alternative signature has %d",
          typeParameters.size(), altFunDeclaration.getTypeParameters().size());
    }

    altTypeParameters = new ArrayList<TypeParameterDescriptor>();

    for (int i = 0, size = typeParameters.size(); i < size; i++) {
      TypeParameterDescriptor originalTypeParamDescriptor = typeParameters.get(i);

      TypeParameterDescriptorImpl altParamDescriptor =
          originalToAltTypeParameters.get(originalTypeParamDescriptor);
      JetTypeParameter altTypeParameter = altFunDeclaration.getTypeParameters().get(i);

      int upperBoundIndex = 0;
      for (JetType upperBound : originalTypeParamDescriptor.getUpperBounds()) {
        JetTypeElement altTypeElement;

        if (upperBoundIndex == 0) {
          JetTypeReference extendsBound = altTypeParameter.getExtendsBound();
          if (extendsBound == null) { // default upper bound
            assert originalTypeParamDescriptor.getUpperBounds().size() == 1;
            altParamDescriptor.addDefaultUpperBound();
            break;
          } else {
            altTypeElement = extendsBound.getTypeElement();
          }
        } else {
          JetTypeConstraint constraint =
              findTypeParameterConstraint(
                  altFunDeclaration, originalTypeParamDescriptor.getName(), upperBoundIndex);
          if (constraint == null) {
            throw new AlternativeSignatureMismatchException(
                "Upper bound #%d for type parameter %s is missing",
                upperBoundIndex, originalTypeParamDescriptor.getName());
          }
          //noinspection ConstantConditions
          altTypeElement = constraint.getBoundTypeReference().getTypeElement();
        }

        assert (altTypeElement != null);

        altParamDescriptor.addUpperBound(
            TypeTransformingVisitor.computeType(
                altTypeElement, upperBound,
                originalToAltTypeParameters, UPPER_BOUND));
        upperBoundIndex++;
      }

      if (findTypeParameterConstraint(
              altFunDeclaration, originalTypeParamDescriptor.getName(), upperBoundIndex)
          != null) {
        throw new AlternativeSignatureMismatchException(
            "Extra upper bound #%d for type parameter %s",
            upperBoundIndex, originalTypeParamDescriptor.getName());
      }

      altParamDescriptor.setInitialized();
      altTypeParameters.add(altParamDescriptor);
    }
  }