diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java index 88ac93b5e28c..826bda927f36 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java @@ -16,6 +16,7 @@ package com.intellij.psi.impl.source.resolve.graphInference.constraints; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil; import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession; @@ -125,8 +126,10 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm } if (applicableMethodReturnType != null) { - final PsiType capturedReturnType = PsiUtil.captureToplevelWildcards(psiSubstitutor.substitute(applicableMethodReturnType), myExpression); - constraints.add(new TypeCompatibilityConstraint(returnType, session.substituteWithInferenceVariables(capturedReturnType))); + applicableMethodReturnType = psiSubstitutor.substitute(applicableMethodReturnType); + applicableMethodReturnType = Registry.is("unsound.capture.conversion.java.spec.change") ? applicableMethodReturnType + : PsiUtil.captureToplevelWildcards(applicableMethodReturnType, myExpression); + constraints.add(new TypeCompatibilityConstraint(returnType, session.substituteWithInferenceVariables(applicableMethodReturnType))); } } return true; @@ -164,7 +167,7 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm if (element instanceof PsiMethod) { final PsiMethod method = (PsiMethod)element; - final PsiType referencedMethodReturnType; + PsiType referencedMethodReturnType; final PsiClass containingClass = method.getContainingClass(); LOG.assertTrue(containingClass != null, method); PsiSubstitutor psiSubstitutor = getSubstitutor(signature, qualifierResolveResult, method, containingClass, myExpression); @@ -211,8 +214,10 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm session.initBounds(myExpression, containingClass.getTypeParameters()); } - final PsiType capturedReturnType = PsiUtil.captureToplevelWildcards(psiSubstitutor.substitute(referencedMethodReturnType), myExpression); - constraints.add(new TypeCompatibilityConstraint(returnType, session.substituteWithInferenceVariables(capturedReturnType))); + referencedMethodReturnType = psiSubstitutor.substitute(referencedMethodReturnType); + referencedMethodReturnType = Registry.is("unsound.capture.conversion.java.spec.change") ? referencedMethodReturnType + : PsiUtil.captureToplevelWildcards(referencedMethodReturnType, myExpression); + constraints.add(new TypeCompatibilityConstraint(returnType, session.substituteWithInferenceVariables(referencedMethodReturnType))); } return true; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/RegistryOptionToSkipUnsoundCaptureConversionInMethodReferenceReturnType.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/RegistryOptionToSkipUnsoundCaptureConversionInMethodReferenceReturnType.java new file mode 100644 index 000000000000..613d535def8e --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/RegistryOptionToSkipUnsoundCaptureConversionInMethodReferenceReturnType.java @@ -0,0 +1,15 @@ +import java.util.Optional; +import java.util.function.Function; + +abstract class View { + { + foo(View::returnType).orElse(void.class); + } + + abstract Optional foo(Function f); + + public Class returnType() { + return null; + } +} + diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java index e38918cd2d3c..b206ca7452cc 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java @@ -156,6 +156,7 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { public void testGetClassReturnTypeInMethodReference() { doTest(); } public void testCaptureTypeOfNewArrayExpression() { doTest(); } public void testIDEA152659() { doTest(); } + public void testRegistryOptionToSkipUnsoundCaptureConversionInMethodReferenceReturnType() { doTest(); } public void testFreshVariableLowerBoundsDuringSuperTypeChecks() { doTest(); } public void testTypeParameterInstantiation() { doTest(); } public void testIgnoreForeignVariables() { doTest(); } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 6a518fdf1268..7ab96efc6eb3 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -809,6 +809,9 @@ javac.fresh.variables.for.captured.wildcards.only=true javac.fresh.variables.for.captured.wildcards.only.description=JLS 18.5.2: if R \u03B8 is a parameterized type, G, and one of A1, ..., An is a wildcard, then, for fresh inference variables \u03B21, ..., \u03B2n ... \ Javac creates fresh variables only for i: Ai is a wildcard +unsound.capture.conversion.java.spec.change=true +unsound.capture.conversion.java.spec.change.description=Capture in method reference return type is unsound and the spec would be changed, see https://bugs.openjdk.java.net/browse/JDK-8170887 + check.power.supply.for.mbp=false check.power.supply.for.mbp.description=Check for discrete video card and power supply on MBPs