new inference: highlight method refs with incompatible inferred bounds

(cherry picked from commit e1af6d1b69f93db6915d3c4f86eaee95389607d2)
This commit is contained in:
anna
2013-11-25 16:48:12 +01:00
parent fc58e5e0af
commit 9ac34fc2ce
4 changed files with 73 additions and 3 deletions
@@ -59,11 +59,11 @@ public class GenericsHighlightUtil {
private GenericsHighlightUtil() { }
@Nullable
public static HighlightInfo checkInferredTypeArguments(PsiMethod genericMethod,
PsiMethodCallExpression call,
public static HighlightInfo checkInferredTypeArguments(PsiTypeParameterListOwner listOwner,
PsiElement call,
PsiSubstitutor substitutor) {
final Pair<PsiTypeParameter, PsiType> inferredTypeArgument =
GenericsUtil.findTypeParameterWithBoundError(genericMethod.getTypeParameters(), substitutor, call, false);
GenericsUtil.findTypeParameterWithBoundError(listOwner.getTypeParameters(), substitutor, call, false);
if (inferredTypeArgument != null) {
final PsiType extendsType = inferredTypeArgument.second;
final PsiTypeParameter typeParameter = inferredTypeArgument.first;
@@ -1246,6 +1246,10 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (!myHolder.hasErrorResults()) {
myHolder.add(HighlightUtil.checkUnhandledExceptions(expression, expression.getTextRange()));
}
if (!myHolder.hasErrorResults() && method instanceof PsiTypeParameterListOwner) {
myHolder.add(GenericsHighlightUtil.checkInferredTypeArguments((PsiTypeParameterListOwner)method, expression, result.getSubstitutor()));
}
}
@Override
@@ -0,0 +1,62 @@
class Test {
interface I1 {
void m(String s);
}
interface I2 {
void m(Integer s);
}
interface I3 {
void m(Object o);
}
static class Foo<X extends Number> {
Foo(X x) { }
}
static <X extends Number> void foo(X x) { }
static void meth1(I1 s) { }
static void meth2(I2 s) { }
static void meth3(I3 s) { }
static void meth4(I1 s) { }
static void meth4(I2 s) { }
static void meth4(I3 s) { }
static {
meth1<error descr="'meth1(Test.I1)' in 'Test' cannot be applied to '(<method reference>)'">(Foo::new)</error>;
meth2(Foo::new);
meth3<error descr="'meth3(Test.I3)' in 'Test' cannot be applied to '(<method reference>)'">(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>);
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>;
}
<X extends Number> void fooInstance(X x) { }
interface II1 {
<X extends String> void m(X x);
}
interface II2 {
<X extends Integer> void m(X x);
}
interface II3 {
<X> void m(X x);
}
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>;
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>;
}
}
@@ -108,6 +108,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testHighlightReferenceWhenContradictBoundsAreInferred() throws Exception {
doTest();
}
private void doTest() {
doTest(false);
}