mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
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
This commit is contained in:
+1
-37
@@ -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<PsiType> upperBounds) {
|
||||
return findParameterizationOfTheSameGenericClass(upperBounds, new Processor<Pair<PsiType, PsiType>>() {
|
||||
return mySession.findParameterizationOfTheSameGenericClass(upperBounds, new Processor<Pair<PsiType, PsiType>>() {
|
||||
@Override
|
||||
public boolean process(Pair<PsiType, PsiType> pair) {
|
||||
final PsiType sType = pair.first;
|
||||
@@ -296,39 +293,6 @@ public class InferenceIncorporationPhase {
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean findParameterizationOfTheSameGenericClass(List<PsiType> upperBounds, Processor<Pair<PsiType, PsiType>> 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<PsiClass> 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<PsiClass> 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);
|
||||
}
|
||||
|
||||
+37
-3
@@ -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<PsiType> bounds = inferenceVariable.getBounds(InferenceBound.LOWER);
|
||||
final Processor<Pair<PsiType, PsiType>> differentParameterizationProcessor = new Processor<Pair<PsiType, PsiType>>() {
|
||||
@@ -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<PsiType> 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<PsiType> upperBounds,
|
||||
Processor<Pair<PsiType, PsiType>> 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<PsiClass> 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<PsiClass> 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;
|
||||
}
|
||||
}
|
||||
|
||||
+17
-1
@@ -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<PsiClassType> result = new ArrayList<PsiClassType>();
|
||||
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) {
|
||||
|
||||
+1
-1
@@ -2,6 +2,6 @@ class A<T> {
|
||||
<T extends A<T>> void foo(T x){}
|
||||
|
||||
void bar(A<?> x){
|
||||
<error descr="Inferred type 'java.lang.Object' for type parameter 'T' is not within its bound; should extend 'A<java.lang.Object>'">foo(x)</error>;
|
||||
foo<error descr="'foo(T)' in 'A' cannot be applied to '(A<capture<?>>)'">(x)</error>;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-7
@@ -4,45 +4,45 @@ abstract class A<T> {
|
||||
<K> void baz37(B<K, ? extends K> a) {}
|
||||
abstract B<T,? extends T> foo37();
|
||||
void bar37(A<?> a){
|
||||
baz37<error descr="'baz37(B<java.lang.Object,?>)' in 'A' cannot be applied to '(B<capture<?>,capture<?>>)'">(a.foo37())</error>;
|
||||
baz37<error descr="'baz37(B<K,? extends K>)' in 'A' cannot be applied to '(B<capture<?>,capture<?>>)'">(a.foo37())</error>;
|
||||
}
|
||||
|
||||
<K> void baz39(B<K, ? extends K> a) {}
|
||||
abstract B<T,? extends T> foo39();
|
||||
void bar39(A<? extends T> a){
|
||||
baz39<error descr="'baz39(B<java.lang.Object,?>)' in 'A' cannot be applied to '(B<capture<? extends T>,capture<? extends T>>)'">(a.foo39())</error>;
|
||||
baz39<error descr="'baz39(B<K,? extends K>)' in 'A' cannot be applied to '(B<capture<? extends T>,capture<? extends T>>)'">(a.foo39())</error>;
|
||||
}
|
||||
|
||||
<K> void baz52(B<K, ? extends K> a) {}
|
||||
abstract B<? extends T,? extends T> foo52();
|
||||
void bar52(A<?> a){
|
||||
baz52<error descr="'baz52(B<java.lang.Object,?>)' in 'A' cannot be applied to '(B<capture<?>,capture<?>>)'">(a.foo52())</error>;
|
||||
baz52<error descr="'baz52(B<K,? extends K>)' in 'A' cannot be applied to '(B<capture<?>,capture<?>>)'">(a.foo52())</error>;
|
||||
}
|
||||
|
||||
<K> void baz54(B<K, ? extends K> a) {}
|
||||
abstract B<? extends T,? extends T> foo54();
|
||||
void bar54(A<? extends T> a){
|
||||
baz54<error descr="'baz54(B<java.lang.Object,?>)' in 'A' cannot be applied to '(B<capture<? extends T>,capture<? extends T>>)'">(a.foo54())</error>;
|
||||
baz54<error descr="'baz54(B<K,? extends K>)' in 'A' cannot be applied to '(B<capture<? extends T>,capture<? extends T>>)'">(a.foo54())</error>;
|
||||
}
|
||||
|
||||
|
||||
<K> void baz58(B<K, ? extends K> a) {}
|
||||
abstract B<?,?> foo58();
|
||||
void bar58(A<?> a){
|
||||
baz58<error descr="'baz58(B<java.lang.Object,?>)' in 'A' cannot be applied to '(B<capture<?>,capture<?>>)'">(a.foo58())</error>;
|
||||
baz58<error descr="'baz58(B<K,? extends K>)' in 'A' cannot be applied to '(B<capture<?>,capture<?>>)'">(a.foo58())</error>;
|
||||
}
|
||||
|
||||
|
||||
<K> void baz59(B<K, ? extends K> a) {}
|
||||
abstract B<?,?> foo59();
|
||||
void bar59(A<? super T> a){
|
||||
baz59<error descr="'baz59(B<java.lang.Object,?>)' in 'A' cannot be applied to '(B<capture<?>,capture<?>>)'">(a.foo59())</error>;
|
||||
baz59<error descr="'baz59(B<K,? extends K>)' in 'A' cannot be applied to '(B<capture<?>,capture<?>>)'">(a.foo59())</error>;
|
||||
}
|
||||
|
||||
|
||||
<K> void baz60(B<K, ? extends K> a) {}
|
||||
abstract B<?,?> foo60();
|
||||
void bar60(A<? extends T> a){
|
||||
baz60<error descr="'baz60(B<java.lang.Object,?>)' in 'A' cannot be applied to '(B<capture<?>,capture<?>>)'">(a.foo60())</error>;
|
||||
baz60<error descr="'baz60(B<K,? extends K>)' in 'A' cannot be applied to '(B<capture<?>,capture<?>>)'">(a.foo60())</error>;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -142,7 +142,7 @@ class S1 {
|
||||
}
|
||||
|
||||
void bar(List<? extends S1> k) {
|
||||
f<error descr="'f(java.util.List<java.lang.Object>, java.lang.Object)' in 'S1' cannot be applied to '(java.util.List<capture<? extends S1>>, S1)'">(k, k.get(0))</error>;
|
||||
f<error descr="'f(java.util.List<T>, T)' in 'S1' cannot be applied to '(java.util.List<capture<? extends S1>>, S1)'">(k, k.get(0))</error>;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -3,5 +3,5 @@ import java.util.Map;
|
||||
class SOE {
|
||||
|
||||
public static <K extends M, M extends Map<K,M>> M foo() {return null;}
|
||||
public static <K1 extends M1, M1 extends Map<K1,M1>> Map<K1, M1> foo1() {<error descr="Incompatible types. Found: 'M', required: 'java.util.Map<K1,M1>'">return foo();</error>}
|
||||
public static <K1 extends M1, M1 extends Map<K1,M1>> Map<K1, M1> foo1() {return foo();}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user