From d85c70d870f263e1b16ffd00a160e93a6cfceb6d Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Fri, 6 May 2016 17:07:45 +0200 Subject: [PATCH] invocation type inference: don't create fresh variables for all type parameters but only for those where wildcards are used in return type (IDEA-155627; IDEA-151220; IDEA-151387) --- .../graphInference/InferenceSession.java | 26 +++++++++++-- ...dcardPlacesDuringReturnTypeProcessing.java | 38 +++++++++++++++++++ .../GraphInferenceHighlightingTest.java | 4 ++ .../util/resources/misc/registry.properties | 4 ++ 4 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/CreateFreshVariablesOnlyForWildcardPlacesDuringReturnTypeProcessing.java 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 7961cda3b808..54df74f1c81b 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 @@ -19,6 +19,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.graphInference.constraints.*; @@ -700,15 +701,15 @@ public class InferenceSession { LOG.assertTrue(returnType instanceof PsiClassType); PsiClassType substitutedCapture = (PsiClassType)PsiUtil.captureToplevelWildcards(returnType, myContext); final PsiTypeParameter[] typeParameters = psiClass.getTypeParameters(); - final InferenceVariable[] copy = initBounds(null, typeParameters); - final PsiType[] parameters = substitutedCapture.getParameters(); + final InferenceVariable[] copy = initFreshVariablesForCapturedBounds(typeParameters, parameters); final PsiType[] newParameters = new PsiType[parameters.length]; final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myManager.getProject()); + int idx = 0; for (int i = 0; i < parameters.length; i++) { newParameters[i] = parameters[i]; if (parameters[i] instanceof PsiCapturedWildcardType) { - newParameters[i] = elementFactory.createType(copy[i]); + newParameters[i] = elementFactory.createType(copy[idx++]); } } substitutedCapture = elementFactory.createType(psiClass, newParameters); @@ -731,6 +732,25 @@ public class InferenceSession { } } + private InferenceVariable[] initFreshVariablesForCapturedBounds(PsiTypeParameter[] typeParameters, PsiType[] parameters) { + if (Registry.is("javac.fresh.variables.for.captured.wildcards.only")) { + final List capturedParams = new ArrayList(); + + PsiSubstitutor restParamSubstitution = PsiSubstitutor.EMPTY; + for (int i = 0; i < parameters.length; i++) { + PsiType parameter = parameters[i]; + if (parameter instanceof PsiCapturedWildcardType) { + capturedParams.add(typeParameters[i]); + } + else { + restParamSubstitution = restParamSubstitution.put(typeParameters[i], parameter); + } + } + return initBounds(null, restParamSubstitution, capturedParams.toArray(new PsiTypeParameter[0])); + } + return initBounds(null, typeParameters); + } + private InferenceVariable shouldResolveAndInstantiate(PsiType returnType, PsiType targetType) { final InferenceVariable inferenceVariable = getInferenceVariable(returnType); if (inferenceVariable != null) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/CreateFreshVariablesOnlyForWildcardPlacesDuringReturnTypeProcessing.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/CreateFreshVariablesOnlyForWildcardPlacesDuringReturnTypeProcessing.java new file mode 100644 index 000000000000..e8153f619038 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/CreateFreshVariablesOnlyForWildcardPlacesDuringReturnTypeProcessing.java @@ -0,0 +1,38 @@ + +class Test { + static class IterableSubject, C> {} + + public static IterableSubject, J> bar(Iterable target) { + return foo(target); + } + + public static IterableSubject, J> foo(Iterable target) { + return null; + } + +} + +abstract class Test1 { + private class XBreakpoint

{} + private class XBreakpointType, P> {} + + abstract > XBreakpointType + findBreakpointType( Class> typeClass); + + > void createXBreakpoint(Class> typeCls) { + final XBreakpointType type = findBreakpointType(typeCls); + } + +} + +class Test2 { + static abstract class AbstractIterableAssert, A extends Iterable, T> {} + + public static AbstractIterableAssert, T1> bar(Iterable actual) { + return foo(actual); + } + + public static AbstractIterableAssert, T> foo(Iterable actual) { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java index 89951b7c2495..62d5a4ae0720 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java @@ -468,6 +468,10 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase } } + public void testCreateFreshVariablesOnlyForWildcardPlacesDuringReturnTypeProcessing() throws Exception { + doTest(); + } + private void doTest() throws Exception { doTest(false); } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 50f50b06f13a..76391c3ee207 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -623,6 +623,10 @@ linux.jdk.accessibility.atkwrapper.block=true javac.unchecked.subtyping.during.incorporation=true javac.unchecked.subtyping.during.incorporation.description=Javac performs unchecked subtyping during incorporation, accepting code which is rejected by the spec and by the eclipse compiler +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 + check.power.supply.for.mbp=false check.power.supply.for.mbp.description=Check for discrete video card and power supply on MBPs