@Nullable
  public static GrSignature getLeastUpperBound(@NotNull GrSignature signature1,
                                               @NotNull GrSignature signature2,
                                               @NotNull PsiManager manager) {
    GrClosureParameter[] parameters1 = signature1.getParameters();
    GrClosureParameter[] parameters2 = signature2.getParameters();

    if (parameters1.length == parameters2.length) {
      GrClosureParameter[] params = new GrClosureParameter[parameters1.length];
      for (int i = 0; i < params.length; i++) {
        final PsiType type = GenericsUtil.getGreatestLowerBound(parameters1[i].getType(), parameters2[i].getType());
        boolean opt = parameters1[i].isOptional() && parameters2[i].isOptional();
        String name = StringUtil.equals(parameters1[i].getName(), parameters2[i].getName()) ? parameters1[i].getName() : null;
        params[i] = new GrImmediateClosureParameterImpl(type, name, opt, null);
      }
      final PsiType s1type = signature1.getReturnType();
      final PsiType s2type = signature2.getReturnType();
      PsiType returnType = null;
      if (s1type != null && s2type != null) {
        returnType = TypesUtil.getLeastUpperBound(s1type, s2type, manager);
      }
      boolean isVarArgs = signature1.isVarargs() && signature2.isVarargs();
      return new GrImmediateClosureSignatureImpl(params, returnType, isVarArgs, false);
    }
    return null; //todo
  }
@Nullable
  public static GrSignature getLeastUpperBound(@NotNull GrSignature signature1,
                                               @NotNull GrSignature signature2,
                                               @NotNull PsiManager manager)