[java] inference: completely ignore expressions over which overload resolution is started

logging for EA-241551 - NPE: MethodReferenceResolver$0$0.inferTypeArguments, as there is no reproducible example, still

GitOrigin-RevId: 46216cd8171479d14af2283cf9cd4a35e68d9b48
This commit is contained in:
Anna Kozlova
2022-07-04 11:47:40 +02:00
committed by intellij-monorepo-bot
parent 5ad2a37900
commit 3db82d3846
5 changed files with 55 additions and 15 deletions

View File

@@ -1,10 +1,10 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.psi;
import com.intellij.codeInsight.AnnotationTargetUtil;
import com.intellij.core.JavaPsiBundle;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
@@ -486,7 +486,10 @@ public final class LambdaUtil {
if (results != null) {
final Set<PsiType> types = new HashSet<>();
for (JavaResolveResult result : results) {
final PsiType functionalExpressionType = MethodCandidateInfo.ourOverloadGuard.doPreventingRecursion(functionalExpression, false, () -> getSubstitutedType(functionalExpression, true, lambdaIdx, result));
Computable<PsiType> computeType = () -> getSubstitutedType(functionalExpression, true, lambdaIdx, result);
final PsiType functionalExpressionType = results.length == 1
? computeType.compute()
: MethodCandidateInfo.ourOverloadGuard.doPreventingRecursion(functionalExpression, false, computeType);
if (functionalExpressionType != null && types.add(functionalExpressionType)) {
overloadProcessor.consume(functionalExpressionType);
}

View File

@@ -405,13 +405,12 @@ public class InferenceSession {
final PsiSubstitutor nestedSubstitutor = myInferenceSessionContainer.findNestedSubstitutor(arg, myInferenceSubstitution);
final PsiType parameterType = nestedSubstitutor.substitute(getParameterType(parameters, i, siteSubstitutor, varargs));
if (parameterType == null) continue;
ExpressionCompatibilityConstraint compatibilityConstraint = new ExpressionCompatibilityConstraint(arg, parameterType);
if (arg instanceof PsiFunctionalExpression && ignoreLambdaConstraintTree(arg) || dependsOnIgnoredConstraint(ignoredConstraints, compatibilityConstraint)) {
ignoredConstraints.add(compatibilityConstraint);
continue;
}
if (!isPertinentToApplicability(arg, parentMethod)) {
ExpressionCompatibilityConstraint compatibilityConstraint = new ExpressionCompatibilityConstraint(arg, parameterType);
if (arg instanceof PsiFunctionalExpression && ignoreLambdaConstraintTree(arg) || dependsOnIgnoredConstraint(ignoredConstraints, compatibilityConstraint)) {
ignoredConstraints.add(compatibilityConstraint);
continue;
}
additionalConstraints.add(compatibilityConstraint);
}
additionalConstraints.add(new CheckedExceptionCompatibilityConstraint(arg, parameterType));

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.psi.impl.source.tree.java;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.ParameterTypeInferencePolicy;
@@ -18,6 +19,7 @@ import com.intellij.psi.util.MethodSignature;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.SmartList;
import com.intellij.util.containers.FactoryMap;
import org.jetbrains.annotations.NotNull;
@@ -26,9 +28,10 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class MethodReferenceResolver implements ResolveCache.PolyVariantContextResolver<PsiMethodReferenceExpressionImpl> {
private static final Logger LOG = Logger.getInstance(MethodReferenceResolver.class);
@Override
public JavaResolveResult @NotNull [] resolve(@NotNull PsiMethodReferenceExpressionImpl reference, @NotNull PsiFile containingFile, boolean incompleteCode) {
PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(reference);
@@ -96,12 +99,19 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
@NotNull
@Override
public PsiSubstitutor inferTypeArguments(@NotNull ParameterTypeInferencePolicy policy, boolean includeReturnConstraint) {
return includeReturnConstraint ? inferTypeArguments(true)
: Objects.requireNonNull(MethodCandidateInfo.ourOverloadGuard
.doPreventingRecursion(reference, false,
() -> inferTypeArguments(false)));
if (includeReturnConstraint) {
return inferTypeArguments(true);
}
PsiSubstitutor psiSubstitutor = MethodCandidateInfo.ourOverloadGuard
.doPreventingRecursion(reference, false, () -> inferTypeArguments(false));
if (psiSubstitutor == null) {
LOG.error("Recursive call for: " + ObjectUtils.notNull(LambdaUtil.treeWalkUp(reference), reference).getText());
return substitutor;
}
return psiSubstitutor;
}
@NotNull
private PsiSubstitutor inferTypeArguments(boolean includeReturnConstraint) {
if (interfaceMethod == null) return substitutor;
InferenceSession session = new InferenceSession(method.getTypeParameters(), substitutor, reference.getManager(), reference);

View File

@@ -0,0 +1,17 @@
import java.util.function.BiFunction;
import java.util.function.Function;
public class Clazz {
<T> T foo(BiFunction<T, T, T> d) { return null;}
<T> T foo(Function<T, String> d) { return null;}
{
fooBar(foo(this::<caret>bar));
}
<K> void fooBar(K k) {}
}

View File

@@ -4,6 +4,8 @@ package com.intellij.java.codeInsight.daemon.lambda;
import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.ExpectedTypesProvider;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import com.intellij.codeInsight.daemon.impl.quickfix.CreateMethodFromMethodReferenceFix;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
import com.intellij.psi.infos.CandidateInfo;
@@ -36,6 +38,15 @@ public class Java8ExpressionsCheckTest extends LightDaemonAnalyzerTestCase {
assertFalse(call.resolveMethodGenerics().isValidResult());
}
public void testCreateMethodFromMethodReferenceAvailability() {
configure();
PsiFile file = getFile();
Editor editor = getEditor();
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
PsiMethodReferenceExpression methodReference = PsiTreeUtil.getParentOfType(element, PsiMethodReferenceExpression.class);
assertTrue(new CreateMethodFromMethodReferenceFix(methodReference).isAvailable(getProject(), editor, file));
}
public void testNestedLambdaReturnTypeCheck() {
configure();
PsiMethodCallExpression