boolean (InferenceSession session, List<? super ConstraintFormula> constraints) { if (!LambdaUtil.isFunctionalType(myT)) { session.registerIncompatibleErrorMessage( JavaPsiBundle.message("error.incompatible.type.not.a.functional.interface", session.getPresentableText(myT))); return false; } final PsiType groundTargetType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(myT, myExpression, false); final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(groundTargetType); final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult); if (interfaceMethod == null) { session.registerIncompatibleErrorMessage( JavaPsiBundle.message("error.incompatible.type.no.valid.function.type.found", session.getPresentableText(myT))); return false; } final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(interfaceMethod, resolveResult); final PsiParameter[] parameters = interfaceMethod.getParameterList().getParameters(); final PsiParameter[] lambdaParameters = myExpression.getParameterList().getParameters(); if (lambdaParameters.length != parameters.length) { session.registerIncompatibleErrorMessage(JavaPsiBundle.message("error.incompatible.type.incompatible.parameter.types.in.lambda", parameters.length, lambdaParameters.length)); return false; } if (myExpression.hasFormalParameterTypes()) { for (int i = 0; i < lambdaParameters.length; i++) { constraints.add(new TypeEqualityConstraint(lambdaParameters[i].getType(), session.substituteWithInferenceVariables(substitutor.substitute(parameters[i].getType())))); } constraints.add(new StrictSubtypingConstraint(myT, groundTargetType)); } else { for (PsiParameter parameter : parameters) { final PsiType type = session.substituteWithInferenceVariables(substitutor.substitute(parameter.getType())); if (!session.isProperType(type)) { //session.registerIncompatibleErrorMessage("Parameter type in not yet inferred: " + session.getPresentableText(type)); return false; } } } PsiType returnType = interfaceMethod.getReturnType(); if (returnType != null) { final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions(myExpression); final PsiElement lambdaBody = myExpression.getBody(); if (returnType.equals(PsiTypes.voidType())) { if (!(lambdaBody instanceof PsiCodeBlock && myExpression.isVoidCompatible()) && !LambdaUtil.isExpressionStatementExpression(lambdaBody)) { session.registerIncompatibleErrorMessage(JavaPsiBundle.message("error.incompatible.type.incompatible.types.expected.void.lambda")); return false; } } else { if (lambdaBody instanceof PsiCodeBlock && !myExpression.isValueCompatible()) { session.registerIncompatibleErrorMessage(JavaPsiBundle.message("error.incompatible.type.expected.value.lambda")); return false; } final PsiSubstitutor nestedSubstitutor = session.getInferenceSessionContainer().findNestedSubstitutor(myExpression, session.getInferenceSubstitution()); returnType = nestedSubstitutor.substitute(substitutor.substitute(returnType)); boolean isProperType = InferenceSession.collectDependencies(returnType, null, type -> { final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(type); return psiClass instanceof InferenceVariable && nestedSubstitutor.getSubstitutionMap().containsValue(type) ? (InferenceVariable)psiClass : null; }); if (!isProperType || myExpression.hasFormalParameterTypes()) { for (PsiExpression returnExpression : returnExpressions) { if (!InferenceSession.ignoreLambdaConstraintTree(returnExpression)) { constraints.add(new ExpressionCompatibilityConstraint(returnExpression, returnType)); } } } else { for (PsiExpression returnExpression : returnExpressions) { if (!PsiPolyExpressionUtil.isPolyExpression(returnExpression)) { if (!TypeConversionUtil.areTypesAssignmentCompatible(returnType, returnExpression)) { final PsiType type = returnExpression.getType(); if (type != null) { session.registerIncompatibleErrorMessage( JavaPsiBundle.message("error.incompatible.type.bad.lambda.return.type", session.getPresentableText(type), session.getPresentableText(returnType))); } else { session.registerIncompatibleErrorMessage( JavaPsiBundle.message("error.incompatible.type", returnExpression.getText(), session.getPresentableText(returnType))); } return false; } } else { //todo check compatibility } } } } } return true; }