private static boolean isMoreSpecificInternal(PsiMethod m1,
                                                PsiMethod m2,
                                                PsiSubstitutor siteSubstitutor1,
                                                PsiExpression[] args,
                                                PsiElement context,
                                                boolean varargs) {

    final InferenceSession session = new InferenceSession(m2.getTypeParameters(), siteSubstitutor1, m2.getManager(), context);

    final PsiParameter[] parameters1 = m1.getParameterList().getParameters();
    final PsiParameter[] parameters2 = m2.getParameterList().getParameters();
    if (!varargs) {
      LOG.assertTrue(parameters1.length == parameters2.length);
    }

    final int paramsLength = !varargs ? parameters1.length : Math.max(parameters1.length, parameters2.length) - 1;
    for (int i = 0; i < paramsLength; i++) {
      PsiType sType = getParameterType(parameters1, i, siteSubstitutor1, varargs);
      PsiType tType = session.substituteWithInferenceVariables(getParameterType(parameters2, i, siteSubstitutor1, varargs));
      if (PsiUtil.isRawSubstitutor(m2, siteSubstitutor1)) {
        tType = TypeConversionUtil.erasure(tType);
      }
      if (sType instanceof PsiClassType &&
          tType instanceof PsiClassType &&
          LambdaUtil.isFunctionalType(sType) && LambdaUtil.isFunctionalType(tType) && !relates(sType, tType)) {
        if (!isFunctionalTypeMoreSpecific(sType, tType, session, args[i])) {
          return false;
        }
      } else {
        if (session.isProperType(tType)) {
          if (!TypeConversionUtil.isAssignable(tType, sType)) {
            return false;
          }
        }
        session.addConstraint(new StrictSubtypingConstraint(tType, sType));
      }
    }

    if (varargs) {
      PsiType sType = getParameterType(parameters1, paramsLength, siteSubstitutor1, true);
      PsiType tType = session.substituteWithInferenceVariables(getParameterType(parameters2, paramsLength, siteSubstitutor1, true));
      session.addConstraint(new StrictSubtypingConstraint(tType, sType));
    }

    return session.repeatInferencePhases();
  }
private static boolean isMoreSpecificInternal(PsiMethod m1,
                                                PsiMethod m2,
                                                PsiSubstitutor siteSubstitutor1,
                                                PsiExpression[] args,
                                                PsiElement context,
                                                boolean varargs)