private void addBoundConstraintsImpl(final PsiType defined, final PsiType type, final ReductionSystem system) {
    final PsiClassType.ClassResolveResult resultDefined = Util.resolveType(defined);
    final PsiClassType.ClassResolveResult resultType = Util.resolveType(type);
    final PsiClass definedClass = resultDefined.getElement();

    if (definedClass == null || !definedClass.equals(resultType.getElement())) {
      return;
    }

    final PsiSubstitutor definedSubst = resultDefined.getSubstitutor();
    final PsiSubstitutor typeSubst = resultType.getSubstitutor();

    for (final PsiTypeParameter parameter : definedSubst.getSubstitutionMap().keySet()) {
      final PsiClassType[] extendsList = parameter.getExtendsList().getReferencedTypes();
      final PsiType definedType = definedSubst.substitute(parameter);

      if (definedType instanceof PsiTypeVariable) {
        for (PsiType extendsType : extendsList) {
          extendsType = replaceWildCards(extendsType, system, definedSubst);

          system.addSubtypeConstraint(definedType, Util.banalize(definedSubst.substitute(extendsType)));
        }
      }
      else {
        addBoundConstraintsImpl(definedType, typeSubst.substitute(parameter), system);
      }
    }
  }
private void addBoundConstraintsImpl(final PsiType defined, final PsiType type, final ReductionSystem system)