mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
inference: simplify bounds check; ensure fresh variables are treated as same, important e.g. in case of diamond operator when inferred types are new each time they are computed (IDEA-131066)
(cherry picked from commit 517c299e336e38bc20d3478191279be2176fbd9b)
This commit is contained in:
@@ -21,10 +21,7 @@ import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.psi.util.TypesDistinctProver;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -505,12 +502,12 @@ public class GenericsUtil {
|
||||
|
||||
public static boolean checkNotInBounds(PsiType type, PsiType bound, PsiReferenceParameterList referenceParameterList) {
|
||||
//allow unchecked conversions in method calls but not in type declaration
|
||||
return checkNotInBounds(type, bound, referenceParameterList.getParent() instanceof PsiReferenceExpression);
|
||||
return checkNotInBounds(type, bound, PsiTreeUtil.getParentOfType(referenceParameterList, PsiCallExpression.class) != null);
|
||||
}
|
||||
|
||||
public static boolean checkNotInBounds(PsiType type, PsiType bound, boolean uncheckedConversionByDefault) {
|
||||
if (type instanceof PsiClassType) {
|
||||
return checkNotAssignable(bound, type, allowUncheckedConversions((PsiClassType)type, uncheckedConversionByDefault));
|
||||
return checkNotAssignable(bound, type, uncheckedConversionByDefault);
|
||||
}
|
||||
if (type instanceof PsiWildcardType) {
|
||||
if (((PsiWildcardType)type).isExtends()) {
|
||||
@@ -581,18 +578,4 @@ public class GenericsUtil {
|
||||
return !TypeConversionUtil.isAssignable(bound, type, allowUncheckedConversion);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean allowUncheckedConversions(PsiClassType type, boolean uncheckedConversionByDefault) {
|
||||
final PsiClass psiClass = type.resolve();
|
||||
if (psiClass != null) {
|
||||
for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(psiClass)) {
|
||||
if (parameter.getExtendsListTypes().length != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (psiClass instanceof PsiTypeParameter && psiClass.getExtendsListTypes().length != 0) return false;
|
||||
}
|
||||
if (!type.isRaw()) return true;
|
||||
return uncheckedConversionByDefault;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.filters.OrFilter;
|
||||
import com.intellij.psi.impl.source.ClassInnerStuffCache;
|
||||
import com.intellij.psi.impl.source.PsiImmediateClassType;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.scope.ElementClassFilter;
|
||||
import com.intellij.psi.scope.ElementClassHint;
|
||||
@@ -1005,7 +1006,7 @@ public class PsiClassImplUtil {
|
||||
PsiTypeParameter p2 = (PsiTypeParameter)another;
|
||||
|
||||
return p1.getIndex() == p2.getIndex() &&
|
||||
aClass.getManager().areElementsEquivalent(p1.getOwner(), p2.getOwner());
|
||||
(aClass.getManager().areElementsEquivalent(p1.getOwner(), p2.getOwner()) || InferenceSession.areSameFreshVariables(p1, p2));
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
|
||||
+11
-2
@@ -42,7 +42,7 @@ import java.util.*;
|
||||
public class InferenceSession {
|
||||
private static final Logger LOG = Logger.getInstance("#" + InferenceSession.class.getName());
|
||||
public static final Key<PsiType> LOWER_BOUND = Key.create("LowBound");
|
||||
|
||||
private static final Key<PsiElement> ORIGINAL_CONTEXT = Key.create("ORIGINAL_CONTEXT");
|
||||
private static final Key<Boolean> ERASED = Key.create("UNCHECKED_CONVERSION");
|
||||
private static final Function<Pair<PsiType, PsiType>, PsiType> UPPER_BOUND_FUNCTION = new Function<Pair<PsiType, PsiType>, PsiType>() {
|
||||
@Override
|
||||
@@ -822,7 +822,11 @@ public class InferenceSession {
|
||||
LOG.assertTrue(file instanceof PsiJavaFile, classText);
|
||||
final PsiClass[] classes = ((PsiJavaFile)file).getClasses();
|
||||
LOG.assertTrue(classes.length == 1, classText);
|
||||
return classes[0].getTypeParameters();
|
||||
final PsiTypeParameter[] parameters = classes[0].getTypeParameters();
|
||||
for (PsiTypeParameter parameter : parameters) {
|
||||
parameter.putUserData(ORIGINAL_CONTEXT, myContext);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private static String getFreshVariableName(InferenceVariable var) {
|
||||
@@ -1394,4 +1398,9 @@ public class InferenceSession {
|
||||
}
|
||||
return s.substitute(type);
|
||||
}
|
||||
|
||||
public static boolean areSameFreshVariables(PsiTypeParameter p1, PsiTypeParameter p2) {
|
||||
final PsiElement originalContext = p1.getUserData(ORIGINAL_CONTEXT);
|
||||
return originalContext != null && originalContext == p2.getUserData(ORIGINAL_CONTEXT);
|
||||
}
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
class Builders {
|
||||
public static A foo() {
|
||||
return new A.Builder<>().create();
|
||||
}
|
||||
|
||||
static class A<K extends A.Builder<K>> {
|
||||
public static class Builder<T extends Builder<T>> {
|
||||
public A<T> create() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
class Builders {
|
||||
public static A foo() {
|
||||
return new A.Builder<>().create();
|
||||
}
|
||||
|
||||
static class A<K extends A.Builder<K>> {
|
||||
public static class Builder<T extends Builder<T>> {
|
||||
public A<T> create() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -384,6 +384,10 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false);
|
||||
}
|
||||
|
||||
public void testInferredParameterInBoundsInRecursiveGenerics() {
|
||||
doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false);
|
||||
}
|
||||
|
||||
public void testHiddenMethodsOfAnonymousClass() throws Exception {
|
||||
doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false);
|
||||
}
|
||||
|
||||
+4
@@ -766,6 +766,10 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
|
||||
doTest(true);
|
||||
}
|
||||
|
||||
public void testInferredParameterInBoundsInRecursiveGenerics() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user