overload resolution for exact method references: ensure param types are equal in case non-generic methods

This commit is contained in:
Anna Kozlova
2015-02-01 16:30:45 +03:00
parent 867a714293
commit 27e575b967
3 changed files with 45 additions and 6 deletions
@@ -1267,7 +1267,7 @@ public class InferenceSession {
final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions((PsiLambdaExpression)arg);
if (LambdaUtil.isFunctionalType(sReturnType) && LambdaUtil.isFunctionalType(tReturnType) &&
if (LambdaUtil.isFunctionalType(sReturnType) && LambdaUtil.isFunctionalType(tReturnType) &&
!TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(sReturnType), TypeConversionUtil.erasure(tReturnType)) &&
!TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(tReturnType), TypeConversionUtil.erasure(sReturnType))) {
@@ -1311,11 +1311,17 @@ public class InferenceSession {
if (arg instanceof PsiMethodReferenceExpression && ((PsiMethodReferenceExpression)arg).isExact()) {
final PsiParameter[] sParameters = sInterfaceMethod.getParameterList().getParameters();
final PsiParameter[] tParameters = tInterfaceMethod.getParameterList().getParameters();
if (session != null) {
LOG.assertTrue(sParameters.length == tParameters.length);
for (int i = 0; i < tParameters.length; i++) {
session.addConstraint(new TypeEqualityConstraint(tSubstitutor.substitute(tParameters[i].getType()),
sSubstitutor.substitute(sParameters[i].getType())));
LOG.assertTrue(sParameters.length == tParameters.length);
for (int i = 0; i < tParameters.length; i++) {
final PsiType tSubstituted = tSubstitutor.substitute(tParameters[i].getType());
final PsiType sSubstituted = sSubstitutor.substitute(sParameters[i].getType());
if (session != null) {
session.addConstraint(new TypeEqualityConstraint(tSubstituted, sSubstituted));
}
else {
if (!Comparing.equal(tSubstituted, sSubstituted)) {
return false;
}
}
}
final PsiType sReturnType = sSubstitutor.substitute(sInterfaceMethod.getReturnType());
@@ -0,0 +1,29 @@
interface I1 {
int i1(int i);
}
interface I2 {
Integer i2(Integer i);
}
interface I3 {
Integer i3(int i);
}
class Test {
private void <warning descr="Private method 'm(I1)' is never used">m</warning>(I1 i1) {System.out.println(i1);}
private void <warning descr="Private method 'm(I2)' is never used">m</warning>(I2 i2) {System.out.println(i2);}
private void m1(I1 i1) {System.out.println(i1);}
private void <warning descr="Private method 'm1(I3)' is never used">m1</warning>(I3 i2) {System.out.println(i2);}
void test() {
m <error descr="Ambiguous method call: both 'Test.m(I1)' and 'Test.m(I2)' match">(this::bar)</error>;
m1(this::bar);
}
int bar(int i) {
return i;
}
}
@@ -75,6 +75,10 @@ public class OverloadResolutionTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testDetectNotEqualParametersInFunctionalTypesForExactMethodReferences() throws Exception {
doTest();
}
private void doTest() {
doTest(true);
}