most specific check for proper functional types fixed

This commit is contained in:
Anna.Kozlova
2016-03-21 18:56:05 +01:00
parent aabf15c80f
commit c5c96608b7
3 changed files with 31 additions and 14 deletions

View File

@@ -741,8 +741,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
if (myArgumentsList instanceof PsiExpressionList) {
final PsiExpression[] expressions = ((PsiExpressionList)myArgumentsList).getExpressions();
if (argId < expressions.length) {
final Specifics specific = isFunctionalTypeMoreSpecific(expressions[argId], right, left);
return Specifics.FIRST.equals(specific);
return isFunctionalTypeMoreSpecific(expressions[argId], right, left);
}
}
return false;
@@ -826,36 +825,31 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
}
}
@NotNull
private static Specifics isFunctionalTypeMoreSpecific(PsiExpression expr, PsiType sType, PsiType tType) {
private static boolean isFunctionalTypeMoreSpecific(PsiExpression expr, PsiType sType, PsiType tType) {
if (expr instanceof PsiParenthesizedExpression) {
return isFunctionalTypeMoreSpecific(((PsiParenthesizedExpression)expr).getExpression(), sType, tType);
}
if (expr instanceof PsiConditionalExpression) {
final Specifics thenSpecifics = isFunctionalTypeMoreSpecific(((PsiConditionalExpression)expr).getThenExpression(), sType, tType);
final Specifics elseSpecifics = isFunctionalTypeMoreSpecific(((PsiConditionalExpression)expr).getElseExpression(), sType, tType);
return thenSpecifics == elseSpecifics ? thenSpecifics : Specifics.NEITHER;
return isFunctionalTypeMoreSpecific(((PsiConditionalExpression)expr).getThenExpression(), sType, tType) &&
isFunctionalTypeMoreSpecific(((PsiConditionalExpression)expr).getElseExpression(), sType, tType);
}
if (expr instanceof PsiFunctionalExpression) {
if (expr instanceof PsiLambdaExpression && !((PsiLambdaExpression)expr).hasFormalParameterTypes()) {
return Specifics.NEITHER;
return false;
}
if (expr instanceof PsiMethodReferenceExpression && !((PsiMethodReferenceExpression)expr).isExact()) {
return Specifics.NEITHER;
return false;
}
if (LambdaUtil.isFunctionalType(sType) && LambdaUtil.isFunctionalType(tType) &&
!TypeConversionUtil.erasure(tType).isAssignableFrom(sType) &&
!TypeConversionUtil.erasure(sType).isAssignableFrom(tType)) {
final boolean specific12 = InferenceSession.isFunctionalTypeMoreSpecificOnExpression(sType, tType, expr);
final boolean specific21 = InferenceSession.isFunctionalTypeMoreSpecificOnExpression(tType, sType, expr);
if (specific12 && !specific21) return Specifics.FIRST;
if (!specific12 && specific21) return Specifics.SECOND;
return InferenceSession.isFunctionalTypeMoreSpecificOnExpression(sType, tType, expr);
}
}
return Specifics.NEITHER;
return false;
}
}

View File

@@ -0,0 +1,19 @@
class Main {
void perform(Runnable r) {
System.out.println(r);
}
<T extends Throwable> void perform(TRunnable<T> r) {
System.out.println(r);
}
interface TRunnable<T extends Throwable> {
void run() throws T;
}
{
<error descr="Ambiguous method call: both 'Main.perform(Runnable)' and 'Main.perform(TRunnable<RuntimeException>)' match">perform</error>(() -> {});
}
}

View File

@@ -221,6 +221,10 @@ public class OverloadResolutionTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testSpecificFunctionalInterfaces() throws Exception {
doTest();
}
private void doTest() {
doTest(true);
}