new inference: reject to infer variables if it's upper bound doesn't agree with lower/equal bound (when present)

This commit is contained in:
Anna Kozlova
2015-02-19 13:23:30 +01:00
parent 7bdb789b45
commit b06817081b
8 changed files with 23 additions and 15 deletions

View File

@@ -864,6 +864,7 @@ public class InferenceSession {
}
private PsiSubstitutor resolveSubset(Collection<InferenceVariable> vars, PsiSubstitutor substitutor) {
nextVar:
for (InferenceVariable var : vars) {
LOG.assertTrue(var.getInstantiation() == PsiType.NULL);
final PsiTypeParameter typeParameter = var.getParameter();
@@ -895,6 +896,13 @@ public class InferenceSession {
type = myErased ? null : upperBound;
}
}
else {
for (PsiType upperType : var.getBounds(InferenceBound.UPPER)) {
if (isProperType(upperType) && !TypeConversionUtil.isAssignable(substitutor.substitute(upperType), lowerBound)) {
continue nextVar;
}
}
}
substitutor = substitutor.put(typeParameter, type);
}

View File

@@ -3,6 +3,6 @@ abstract class A<S> {
{
A<?> a = null;
<error descr="Inferred type 'A<capture<?>>' for type parameter 'T' is not within its bound; should extend 'A<? extends java.lang.Throwable>'">foo(a)</error>;
foo<error descr="'foo(T)' in 'A' cannot be applied to '(A<capture<?>>)'">(a)</error>;
}
}

View File

@@ -4,7 +4,7 @@ class CLS {
static <V extends String> void bar (V v) {}
static void foo () {
<error descr="Inferred type 'java.lang.Object' for type parameter 'V' is not within its bound; should extend 'java.lang.String'">bar(new Object())</error>;
bar<error descr="'bar(V)' in 'CLS' cannot be applied to '(java.lang.Object)'">(new Object())</error>;
}
}
//////////////////////////////

View File

@@ -20,7 +20,7 @@ class MyTest {
static void foo(I3 i) {}
static {
foo<error descr="Ambiguous method call: both 'MyTest.foo(I1)' and 'MyTest.foo(I2)' match">(MyTest::m)</error>;
foo<error descr="Cannot resolve method 'foo(<method reference>)'">(MyTest::m)</error>;
foo<error descr="Ambiguous method call: both 'MyTest.foo(I1)' and 'MyTest.foo(I2)' match">(MyTest::m1)</error>;
}
}

View File

@@ -39,6 +39,6 @@ class MyTest1 {
static void foo(I3 i) {}
static {
foo<error descr="Ambiguous method call: both 'MyTest1.foo(I1)' and 'MyTest1.foo(I2)' match">(Foo::new)</error>;
foo<error descr="Cannot resolve method 'foo(<method reference>)'">(Foo::new)</error>;
}
}

View File

@@ -67,7 +67,7 @@ class MyTest1 {
}
public static void main(String[] args) {
m<error descr="Ambiguous method call: both 'MyTest1.m(I1)' and 'MyTest1.m(I2)' match">(Foo::new)</error>;
m<error descr="Ambiguous method call: both 'MyTest1.m(I2)' and 'MyTest1.m(I3)' match">(Foo::new)</error>;
}
}
class MyTest2 {
@@ -104,6 +104,6 @@ class MyTest2 {
}
public static void main(String[] args) {
m<error descr="Ambiguous method call: both 'MyTest2.m(I1)' and 'MyTest2.m(I2)' match">(Foo::new)</error>;
m<error descr="Ambiguous method call: both 'MyTest2.m(I2)' and 'MyTest2.m(I3)' match">(Foo::new)</error>;
}
}

View File

@@ -26,7 +26,7 @@ abstract class NoFormalParamTypeInferenceNeeded {
{
map(a -> zip(text -> text));
zip(a -> zip(text -> text));
Integer zip = zip(<error descr="Cyclic inference">a -> zip(text -> text)</error>);
Integer zip = zip(a -> zip(<error descr="Cyclic inference">text -> text</error>));
}
}

View File

@@ -29,15 +29,15 @@ class Test {
static void meth4(I3 s) { }
static {
meth1(<error descr="Inferred type 'java.lang.String' for type parameter 'X' is not within its bound; should extend 'java.lang.Number'">Foo::new</error>);
meth1(Foo::<error descr="Cannot resolve constructor 'Foo'">new</error>);
meth2(Foo::new);
meth3(<error descr="Inferred type 'java.lang.Object' for type parameter 'X' is not within its bound; should extend 'java.lang.Number'">Foo::new</error>);
meth4<error descr="Ambiguous method call: both 'Test.meth4(I1)' and 'Test.meth4(I2)' match">(Foo::new)</error>;
meth3(Foo::<error descr="Cannot resolve constructor 'Foo'">new</error>);
meth4<error descr="Cannot resolve method 'meth4(<method reference>)'">(Foo::new)</error>;
meth1(<error descr="Inferred type 'java.lang.String' for type parameter 'X' is not within its bound; should extend 'java.lang.Number'">Test::foo</error>);
meth1(Test::<error descr="Cannot resolve method 'foo'">foo</error>);
meth2(Test::foo);
meth3(<error descr="Inferred type 'java.lang.Object' for type parameter 'X' is not within its bound; should extend 'java.lang.Number'">Test::foo</error>);
meth4<error descr="Ambiguous method call: both 'Test.meth4(I1)' and 'Test.meth4(I2)' match">(Test::foo)</error>;
meth3(Test::<error descr="Cannot resolve method 'foo'">foo</error>);
meth4<error descr="Cannot resolve method 'meth4(<method reference>)'">(Test::foo)</error>;
}
@@ -55,8 +55,8 @@ class Test {
}
void test() {
II1 i1 = <error descr="Inferred type 'X' for type parameter 'X' is not within its bound; should extend 'java.lang.Number'">this::fooInstance</error>;
II1 i1 = this::<error descr="Cannot resolve method 'fooInstance'">fooInstance</error>;
II2 i2 = this::fooInstance;
II3 i3 = <error descr="Inferred type 'X' for type parameter 'X' is not within its bound; should extend 'java.lang.Number'">this::fooInstance</error>;
II3 i3 = this::<error descr="Cannot resolve method 'fooInstance'">fooInstance</error>;
}
}