boolean (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(); }