From 7bdb789b45d24e76bc8b7b999e1836d25256527d Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 19 Feb 2015 12:59:40 +0100 Subject: [PATCH] new inference: reject inference if lower and equals bounds do not agree; -> inference variable should fill extends list types with it's upper bounds as they are correctly substituted with session's inference variables, otherwise incorporation up-up rule could get refs to initial type parameter instead of correct inference variable --- .../InferenceIncorporationPhase.java | 38 +----------------- .../graphInference/InferenceSession.java | 40 +++++++++++++++++-- .../graphInference/InferenceVariable.java | 18 ++++++++- .../genericsHighlighting8/IDEA57413.java | 2 +- ...ctEqualsBoundsContradictingLowerBound.java | 14 +++---- .../genericsHighlighting8/Variance.java | 2 +- .../SOEDuringInferenceFromParamBounds.java | 2 +- 7 files changed, 65 insertions(+), 51 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java index 8ee31c32f6ef..a94bec148ac8 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java @@ -21,9 +21,6 @@ import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.graphInference.constraints.ConstraintFormula; import com.intellij.psi.impl.source.resolve.graphInference.constraints.StrictSubtypingConstraint; import com.intellij.psi.impl.source.resolve.graphInference.constraints.TypeEqualityConstraint; -import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.PsiUtil; -import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.Processor; import java.util.*; @@ -283,7 +280,7 @@ public class InferenceIncorporationPhase { * then for all i, 1 ≤ i ≤ n, if Si and Ti are types (not wildcards), the constraint ⟨Si = Ti⟩ is implied. */ private boolean upUp(List upperBounds) { - return findParameterizationOfTheSameGenericClass(upperBounds, new Processor>() { + return mySession.findParameterizationOfTheSameGenericClass(upperBounds, new Processor>() { @Override public boolean process(Pair pair) { final PsiType sType = pair.first; @@ -296,39 +293,6 @@ public class InferenceIncorporationPhase { }); } - public static boolean findParameterizationOfTheSameGenericClass(List upperBounds, Processor> processor) { - for (int i = 0; i < upperBounds.size(); i++) { - final PsiType sBound = upperBounds.get(i); - final PsiClass sClass = PsiUtil.resolveClassInClassTypeOnly(sBound); - if (sClass == null) continue; - final LinkedHashSet superClasses = InheritanceUtil.getSuperClasses(sClass); - superClasses.add(sClass); - for (int j = i + 1; j < upperBounds.size(); j++) { - final PsiType tBound = upperBounds.get(j); - final PsiClass tClass = PsiUtil.resolveClassInClassTypeOnly(tBound); - if (tClass != null) { - - final LinkedHashSet tSupers = InheritanceUtil.getSuperClasses(tClass); - tSupers.add(tClass); - tSupers.retainAll(superClasses); - - for (PsiClass gClass : tSupers) { - final PsiSubstitutor sSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(gClass, (PsiClassType)sBound); - final PsiSubstitutor tSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(gClass, (PsiClassType)tBound); - for (PsiTypeParameter typeParameter : gClass.getTypeParameters()) { - final PsiType sType = sSubstitutor.substitute(typeParameter); - final PsiType tType = tSubstitutor.substitute(typeParameter); - if (!processor.process(Pair.create(sType, tType))) { - return true; - } - } - } - } - } - } - return false; - } - private void addConstraint(ConstraintFormula constraint) { mySession.addConstraint(constraint); } 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 9ec7ab51b059..2f7f1a9c97f7 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 @@ -558,7 +558,7 @@ public class InferenceSession { return false; } - private static boolean hasWildcardParameterization(InferenceVariable inferenceVariable, PsiClassType targetType) { + private boolean hasWildcardParameterization(InferenceVariable inferenceVariable, PsiClassType targetType) { if (!FunctionalInterfaceParameterizationUtil.isWildcardParameterized(targetType)) { final List bounds = inferenceVariable.getBounds(InferenceBound.LOWER); final Processor> differentParameterizationProcessor = new Processor>() { @@ -567,7 +567,7 @@ public class InferenceSession { return pair.first == null || pair.second == null || !TypesDistinctProver.provablyDistinct(pair.first, pair.second); } }; - if (InferenceIncorporationPhase.findParameterizationOfTheSameGenericClass(bounds, differentParameterizationProcessor)) return true; + if (findParameterizationOfTheSameGenericClass(bounds, differentParameterizationProcessor)) return true; final List eqBounds = inferenceVariable.getBounds(InferenceBound.EQ); for (PsiType lowBound : bounds) { if (FunctionalInterfaceParameterizationUtil.isWildcardParameterized(lowBound)) { @@ -878,7 +878,7 @@ public class InferenceSession { PsiType type; if (eqBound != PsiType.NULL && (myErased || eqBound != null)) { if (lowerBound != PsiType.NULL && !TypeConversionUtil.isAssignable(eqBound, lowerBound)) { - type = PsiType.NULL; + continue; } else { type = eqBound; } @@ -1463,4 +1463,38 @@ public class InferenceSession { final PsiElement originalContext = p1.getUserData(ORIGINAL_CONTEXT); return originalContext != null && originalContext == p2.getUserData(ORIGINAL_CONTEXT); } + + public boolean findParameterizationOfTheSameGenericClass(List upperBounds, + Processor> processor) { + for (int i = 0; i < upperBounds.size(); i++) { + final PsiType sBound = upperBounds.get(i); + final PsiClass sClass = PsiUtil.resolveClassInClassTypeOnly(sBound); + if (sClass == null) continue; + final LinkedHashSet superClasses = InheritanceUtil.getSuperClasses(sClass); + superClasses.add(sClass); + for (int j = i + 1; j < upperBounds.size(); j++) { + final PsiType tBound = upperBounds.get(j); + final PsiClass tClass = PsiUtil.resolveClassInClassTypeOnly(tBound); + if (tClass != null) { + + final LinkedHashSet tSupers = InheritanceUtil.getSuperClasses(tClass); + tSupers.add(tClass); + tSupers.retainAll(superClasses); + + for (PsiClass gClass : tSupers) { + final PsiSubstitutor sSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(gClass, (PsiClassType)sBound); + final PsiSubstitutor tSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(gClass, (PsiClassType)tBound); + for (PsiTypeParameter typeParameter : gClass.getTypeParameters()) { + final PsiType sType = sSubstitutor.substitute(typeParameter); + final PsiType tType = tSubstitutor.substitute(typeParameter); + if (!processor.process(Pair.create(sType, tType))) { + return true; + } + } + } + } + } + } + return false; + } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java index da7b4b78930a..3ef51c45ccc4 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java @@ -15,9 +15,13 @@ */ package com.intellij.psi.impl.source.resolve.graphInference; -import com.intellij.psi.*; +import com.intellij.psi.PsiClassType; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiType; +import com.intellij.psi.PsiTypeParameter; import com.intellij.psi.impl.light.LightTypeParameter; import com.intellij.psi.util.PsiUtil; +import org.jetbrains.annotations.NotNull; import java.util.*; @@ -49,6 +53,18 @@ public class InferenceVariable extends LightTypeParameter { myInstantiation = instantiation; } + @NotNull + @Override + public PsiClassType[] getExtendsListTypes() { + final List result = new ArrayList(); + for (PsiType type : getBounds(InferenceBound.UPPER)) { + if (type instanceof PsiClassType) { + result.add((PsiClassType)type); + } + } + return result.toArray(new PsiClassType[result.size()]); + } + public boolean addBound(PsiType classType, InferenceBound inferenceBound) { if (inferenceBound == InferenceBound.EQ && PsiUtil.resolveClassInClassTypeOnly(classType) == this) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57413.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57413.java index f39a0dd85290..699a60db6d01 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57413.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57413.java @@ -2,6 +2,6 @@ class A { > void foo(T x){} void bar(A x){ - foo(x); + foo(x); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/RejectEqualsBoundsContradictingLowerBound.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/RejectEqualsBoundsContradictingLowerBound.java index d5666a102da3..4e48a1f48b3c 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/RejectEqualsBoundsContradictingLowerBound.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/RejectEqualsBoundsContradictingLowerBound.java @@ -4,45 +4,45 @@ abstract class A { void baz37(B a) {} abstract B foo37(); void bar37(A a){ - baz37(a.foo37()); + baz37(a.foo37()); } void baz39(B a) {} abstract B foo39(); void bar39(A a){ - baz39(a.foo39()); + baz39(a.foo39()); } void baz52(B a) {} abstract B foo52(); void bar52(A a){ - baz52(a.foo52()); + baz52(a.foo52()); } void baz54(B a) {} abstract B foo54(); void bar54(A a){ - baz54(a.foo54()); + baz54(a.foo54()); } void baz58(B a) {} abstract B foo58(); void bar58(A a){ - baz58(a.foo58()); + baz58(a.foo58()); } void baz59(B a) {} abstract B foo59(); void bar59(A a){ - baz59(a.foo59()); + baz59(a.foo59()); } void baz60(B a) {} abstract B foo60(); void bar60(A a){ - baz60(a.foo60()); + baz60(a.foo60()); } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/Variance.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/Variance.java index ef8cdec6952e..6b39b49f97c8 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/Variance.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/Variance.java @@ -142,7 +142,7 @@ class S1 { } void bar(List k) { - f(k, k.get(0)); + f(k, k.get(0)); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/SOEDuringInferenceFromParamBounds.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/SOEDuringInferenceFromParamBounds.java index 3d6a1b0ed0a9..24c706f56266 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/SOEDuringInferenceFromParamBounds.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/SOEDuringInferenceFromParamBounds.java @@ -3,5 +3,5 @@ import java.util.Map; class SOE { public static > M foo() {return null;} - public static > Map foo1() {return foo();} + public static > Map foo1() {return foo();} }