private static PsiType getLeastContainingTypeArgument(PsiType type1,
                                                        PsiType type2,
                                                        Set<Couple<PsiType>> compared,
                                                        PsiManager manager) {
    if (type1 instanceof PsiWildcardType) {
      PsiWildcardType wild1 = (PsiWildcardType)type1;
      final PsiType bound1 = wild1.getBound();
      if (bound1 == null) return type1;
      if (type2 instanceof PsiWildcardType) {
        PsiWildcardType wild2 = (PsiWildcardType)type2;
        final PsiType bound2 = wild2.getBound();
        if (bound2 == null) return type2;
        if (wild1.isExtends() == wild2.isExtends()) {
          return wild1.isExtends() ?
                 PsiWildcardType.createExtends(manager, getLeastUpperBound(bound1, bound2, compared, manager)) :
                 PsiWildcardType.createSuper(manager, getGreatestLowerBound(bound1, bound2));
        }
        else {
          return bound1.equals(bound2) ? bound1 : PsiWildcardType.createUnbounded(manager);
        }
      }
      else {
        return wild1.isExtends() ? PsiWildcardType.createExtends(manager, getLeastUpperBound(bound1, type2, compared, manager)) :
               wild1.isSuper() ? PsiWildcardType.createSuper(manager, getGreatestLowerBound(bound1, type2)) :
               wild1;
      }
    }
    else if (type2 instanceof PsiWildcardType) {
      return getLeastContainingTypeArgument(type2, type1, compared, manager);
    }
    //Done with wildcards

    if (type1.equals(type2)) return type1;
    return PsiWildcardType.createExtends(manager, getLeastUpperBound(type1, type2, compared, manager));
  }
private static PsiType getLeastContainingTypeArgument(PsiType type1,
                                                        PsiType type2,
                                                        Set<Couple<PsiType>> compared,
                                                        PsiManager manager)