diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java index 27ae57350355..e8e0a5f66c8e 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java @@ -478,19 +478,8 @@ public class InferenceSession { final PsiSubstitutor nestedSubstitutor = myInferenceSessionContainer.findNestedSubstitutor(arg, myInferenceSubstitution); final PsiType parameterType = nestedSubstitutor.substitute(getParameterType(parameters, i, siteSubstitutor, varargs)); if (!isPertinentToApplicability(arg, parentMethod)) { - if (arg instanceof PsiLambdaExpression) { - for (Object expr : MethodCandidateInfo.ourOverloadGuard.currentStack()) { - if (PsiTreeUtil.getParentOfType((PsiElement)expr, PsiLambdaExpression.class) == arg) { - return; - } - } - - for (Object expr : LambdaUtil.ourParameterGuard.currentStack()) { - if (expr instanceof PsiParameter && ((PsiParameter)expr).getDeclarationScope() == arg) { - ignoredConstraints.add(new ExpressionCompatibilityConstraint(arg, parameterType)); - return; - } - } + if (arg instanceof PsiLambdaExpression && ignoreConstraintTree(ignoredConstraints, arg, parameterType)) { + continue; } additionalConstraints.add(new ExpressionCompatibilityConstraint(arg, parameterType)); } @@ -514,6 +503,22 @@ public class InferenceSession { } } + private static boolean ignoreConstraintTree(Set ignoredConstraints, PsiExpression arg, PsiType parameterType) { + for (Object expr : MethodCandidateInfo.ourOverloadGuard.currentStack()) { + if (PsiTreeUtil.getParentOfType((PsiElement)expr, PsiLambdaExpression.class) == arg) { + return true; + } + } + + for (Object expr : LambdaUtil.ourParameterGuard.currentStack()) { + if (expr instanceof PsiParameter && ((PsiParameter)expr).getDeclarationScope() == arg) { + ignoredConstraints.add(new ExpressionCompatibilityConstraint(arg, parameterType)); + return true; + } + } + return false; + } + public static PsiMethod getCalledMethod(PsiCall arg) { final PsiExpressionList argumentList = arg.getArgumentList(); if (argumentList == null) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/expressions/LambdaParameterTypeSideEffects.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/expressions/LambdaParameterTypeSideEffects.java new file mode 100644 index 000000000000..a7220686a0f0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/expressions/LambdaParameterTypeSideEffects.java @@ -0,0 +1,70 @@ + + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; + +import static java.util.Collections.emptyList; + +class Example { + + public static List map(Function fn, List as) { + return null; + } + + public static B foldLeft(BiFunction fn, B b, List as) { + return null; + } + + public static void main(String[] args) { + List> criteria = emptyList(); + + foldLeft((r, t) -> t.into((s, i) -> null), + new Tuple2, List>(new ArrayList<>(), new ArrayList<>()), + map(CoProduct2::project, criteria)); + } + + public static interface CoProduct2 { + R match(Function aFn, Function bFn); + + default Tuple2, Optional> project() { + return null; + } + } + + public static final class Tuple2 { + public Tuple2(A a, B b) { + } + + public R into(BiFunction fn) { + return null; + } + } +} + +class Example1 { + + private static List map(Function fn, List as) { + return null; + } + + private static void foldLeft(Consumer fn, List as) { } + + public static void foo(final List> criteria) { + foldLeft((t) -> t. into(), + map(CoProduct2::project, criteria)); + } + + public interface CoProduct2 { + default Tuple2 project() { + return null; + } + } + + public static final class Tuple2 { + public void into() { } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/Java8ExpressionsCheckTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/Java8ExpressionsCheckTest.java index 4265fd31ab5e..4fc268dddbb2 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/Java8ExpressionsCheckTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/Java8ExpressionsCheckTest.java @@ -82,6 +82,22 @@ public class Java8ExpressionsCheckTest extends LightDaemonAnalyzerTestCase { doTestAllMethodCallExpressions(); } + public void testLambdaParameterTypeSideEffects() throws Exception { + configureByFile(BASE_PATH + "/" + getTestName(false) + ".java"); + Collection parameters = PsiTreeUtil.findChildrenOfType(getFile(), PsiParameter.class); + for (PsiParameter parameter : parameters) { + if (parameter.getTypeElement() == null) { //lambda parameter + assertNotNull(parameter.getType()); + Collection expressions = PsiTreeUtil.findChildrenOfType(getFile(), PsiCallExpression.class); + for (PsiCallExpression expression : expressions) { + assertNotNull(expression.getText(), expression.resolveMethod()); + } + + getPsiManager().dropResolveCaches(); + } + } + } + public void testCachingOfResultsDuringCandidatesIteration() throws Exception { configureByFile(BASE_PATH + "/" + getTestName(false) + ".java"); final Collection methodCallExpressions = PsiTreeUtil.findChildrenOfType(getFile(), PsiMethodCallExpression.class);