private List<TypeParameterDescriptor> modifyTypeParametersAccordingToSuperMethods(
      List<TypeParameterDescriptor> autoTypeParameters) {
    List<TypeParameterDescriptor> result = Lists.newArrayList();

    for (TypeParameterDescriptor autoParameter : autoTypeParameters) {
      int index = autoParameter.getIndex();
      TypeParameterDescriptorImpl modifiedTypeParameter =
          autoTypeParameterToModified.get(autoParameter);

      List<Iterator<JetType>> upperBoundFromSuperFunctionsIterators = Lists.newArrayList();
      for (FunctionDescriptor superFunction : superFunctions) {
        upperBoundFromSuperFunctionsIterators.add(
            superFunction.getTypeParameters().get(index).getUpperBounds().iterator());
      }

      for (JetType autoUpperBound : autoParameter.getUpperBounds()) {
        List<TypeAndVariance> upperBoundsFromSuperFunctions = Lists.newArrayList();

        for (Iterator<JetType> iterator : upperBoundFromSuperFunctionsIterators) {
          assert iterator.hasNext();
          upperBoundsFromSuperFunctions.add(new TypeAndVariance(iterator.next(), INVARIANT));
        }

        JetType modifiedUpperBound =
            modifyTypeAccordingToSuperMethods(
                autoUpperBound, upperBoundsFromSuperFunctions, UPPER_BOUND);
        modifiedTypeParameter.addUpperBound(modifiedUpperBound);
      }

      for (Iterator<JetType> iterator : upperBoundFromSuperFunctionsIterators) {
        assert !iterator.hasNext();
      }

      modifiedTypeParameter.setInitialized();
      result.add(modifiedTypeParameter);
    }

    return result;
  }