new inference: reject equals bounds contradicting lower bounds

This commit is contained in:
Anna Kozlova
2014-12-17 09:57:48 +01:00
parent f217ed47c4
commit 1ed0901d4b
6 changed files with 71 additions and 6 deletions
@@ -464,7 +464,8 @@ public class InferenceSession {
if (!PsiType.VOID.equals(returnType) && returnType != null) {
PsiType targetType = getTargetType(context);
if (targetType != null && !PsiType.VOID.equals(targetType)) {
registerReturnTypeConstraints(PsiUtil.isRawSubstitutor(method, mySiteSubstitutor) ? returnType : mySiteSubstitutor.substitute(returnType), targetType);
registerReturnTypeConstraints(
PsiUtil.isRawSubstitutor(method, mySiteSubstitutor) ? returnType : mySiteSubstitutor.substitute(returnType), targetType);
}
}
}
@@ -858,14 +859,26 @@ public class InferenceSession {
final PsiType eqBound = getEqualsBound(var, substitutor);
if (eqBound != PsiType.NULL && eqBound instanceof PsiPrimitiveType) continue;
PsiType type = eqBound != PsiType.NULL && (myErased || eqBound != null) ? eqBound : getLowerBound(var, substitutor);
final PsiType lowerBound = getLowerBound(var, substitutor);
final PsiType upperBound = getUpperBound(var, substitutor);
PsiType type;
if (eqBound != PsiType.NULL && (myErased || eqBound != null)) {
if (lowerBound != PsiType.NULL && !TypeConversionUtil.isAssignable(eqBound, lowerBound)) {
type = PsiType.NULL;
} else {
type = eqBound;
}
}
else {
type = lowerBound;
}
if (type == PsiType.NULL) {
if (var.isThrownBound() && isThrowable(var.getBounds(InferenceBound.UPPER))) {
type = PsiType.getJavaLangRuntimeException(myManager, GlobalSearchScope.allScope(myManager.getProject()));
}
else {
if (substitutor.putAll(mySiteSubstitutor).getSubstitutionMap().get(typeParameter) != null) continue;
type = myErased ? null : getUpperBound(var, substitutor);
type = myErased ? null : upperBound;
}
}
substitutor = substitutor.put(typeParameter, type);
@@ -2,6 +2,6 @@ class A<T> {
<T extends A<T>> void foo(T x){}
void bar(A<?> x){
<error descr="Inferred type 'capture<?>' for type parameter 'T' is not within its bound; should extend 'A<capture<? extends A<capture<?>>>>'">foo(x)</error>;
<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>;
}
}
@@ -0,0 +1,48 @@
class B<T1,S> {}
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>;
}
<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>;
}
<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>;
}
<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>;
}
<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>;
}
<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>;
}
<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>;
}
}
@@ -142,7 +142,7 @@ class S1 {
}
void bar(List<? extends S1> k) {
f<error descr="'f(java.util.List<capture<? extends S1>>, capture<? extends S1>)' 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<java.lang.Object>, java.lang.Object)' in 'S1' cannot be applied to '(java.util.List<capture<? extends S1>>, S1)'">(k, k.get(0))</error>;
}
}
@@ -1,6 +1,6 @@
import java.util.Map;
public class SOE {
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>}
@@ -784,6 +784,10 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
doTest(false);
}
public void testRejectEqualsBoundsContradictingLowerBound() throws Exception {
doTest(false);
}
private void doTest() {
doTest(false);
}