new inference: no substitution during most specific inference by means of new spec (IDEA-127584)

This commit is contained in:
Anna Kozlova
2014-07-21 13:17:23 +02:00
parent fb786d36c0
commit 89dc528242
4 changed files with 40 additions and 15 deletions

View File

@@ -1021,13 +1021,13 @@ public class InferenceSession {
*/
public static boolean isMoreSpecific(PsiMethod m1,
PsiMethod m2,
PsiSubstitutor siteSubstitutor2,
PsiExpression[] args,
PsiElement context,
boolean varargs) {
final PsiTypeParameter[] typeParameters = m2.getTypeParameters();
final InferenceSession session = new InferenceSession(typeParameters, siteSubstitutor2, m2.getManager(), context);
final InferenceSession session = new InferenceSession(PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY, m2.getManager(), context);
for (PsiTypeParameter param : PsiUtil.typeParametersIterable(m2)) {
session.initBounds(param);
}
final PsiParameter[] parameters1 = m1.getParameterList().getParameters();
final PsiParameter[] parameters2 = m2.getParameterList().getParameters();
@@ -1037,8 +1037,8 @@ public class InferenceSession {
final int paramsLength = !varargs ? parameters1.length : parameters1.length - 1;
for (int i = 0; i < paramsLength; i++) {
PsiType sType = getParameterType(parameters1, i, siteSubstitutor2, false);
PsiType tType = getParameterType(parameters2, i, siteSubstitutor2, varargs);
PsiType sType = getParameterType(parameters1, i, PsiSubstitutor.EMPTY, false);
PsiType tType = getParameterType(parameters2, i, PsiSubstitutor.EMPTY, varargs);
if (session.isProperType(sType) && session.isProperType(tType)) {
if (!TypeConversionUtil.isAssignable(tType, sType)) {
return false;
@@ -1055,8 +1055,8 @@ public class InferenceSession {
}
if (varargs) {
PsiType sType = getParameterType(parameters1, paramsLength, siteSubstitutor2, true);
PsiType tType = getParameterType(parameters2, paramsLength, siteSubstitutor2, true);
PsiType sType = getParameterType(parameters1, paramsLength, PsiSubstitutor.EMPTY, true);
PsiType tType = getParameterType(parameters2, paramsLength, PsiSubstitutor.EMPTY, true);
session.addConstraint(new StrictSubtypingConstraint(tType, sType));
}

View File

@@ -550,10 +550,10 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
final PsiSubstitutor methodSubstitutor1 = calculateMethodSubstitutor(typeParameters1, method1, siteSubstitutor1, types1, types2AtSite,
languageLevel);
boolean applicable12 = isApplicableTo(types2AtSite, method1, languageLevel, varargsPosition, methodSubstitutor1, method2, siteSubstitutor1);
boolean applicable12 = isApplicableTo(types2AtSite, method1, languageLevel, varargsPosition, methodSubstitutor1, method2);
final PsiSubstitutor methodSubstitutor2 = calculateMethodSubstitutor(typeParameters2, method2, siteSubstitutor2, types2, types1AtSite, languageLevel);
boolean applicable21 = isApplicableTo(types1AtSite, method2, languageLevel, varargsPosition, methodSubstitutor2, method1, siteSubstitutor2);
boolean applicable21 = isApplicableTo(types1AtSite, method2, languageLevel, varargsPosition, methodSubstitutor2, method1);
if (!myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
final boolean typeArgsApplicable12 = GenericsUtil.isTypeArgumentsApplicable(typeParameters1, methodSubstitutor1, myArgumentsList, !applicable21);
@@ -604,9 +604,9 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
if (toCompareFunctional) {
final boolean applicable12ignoreFunctionalType = isApplicableTo(types2AtSite, method1, languageLevel, varargsPosition,
calculateMethodSubstitutor(typeParameters1, method1, siteSubstitutor1, types1, types2AtSite, languageLevel), null, null);
calculateMethodSubstitutor(typeParameters1, method1, siteSubstitutor1, types1, types2AtSite, languageLevel), null);
final boolean applicable21ignoreFunctionalType = isApplicableTo(types1AtSite, method2, languageLevel, varargsPosition,
calculateMethodSubstitutor(typeParameters2, method2, siteSubstitutor2, types2, types1AtSite, languageLevel), null, null);
calculateMethodSubstitutor(typeParameters2, method2, siteSubstitutor2, types2, types1AtSite, languageLevel), null);
if (applicable12ignoreFunctionalType || applicable21ignoreFunctionalType) {
Specifics specifics = null;
@@ -694,12 +694,11 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
@NotNull LanguageLevel languageLevel,
boolean varargsPosition,
@NotNull PsiSubstitutor methodSubstitutor1,
PsiMethod method2,
PsiSubstitutor siteSubstitutor1) {
PsiMethod method2) {
if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && method2 != null && method1.getTypeParameters().length > 0 && myArgumentsList instanceof PsiExpressionList) {
final PsiElement parent = myArgumentsList.getParent();
if (parent instanceof PsiCallExpression && ((PsiCallExpression)parent).getTypeArguments().length == 0) {
return InferenceSession.isMoreSpecific(method2, method1, siteSubstitutor1, ((PsiExpressionList)myArgumentsList).getExpressions(), myArgumentsList, varargsPosition);
return InferenceSession.isMoreSpecific(method2, method1, ((PsiExpressionList)myArgumentsList).getExpressions(), myArgumentsList, varargsPosition);
}
}
final int applicabilityLevel = PsiUtil.getApplicabilityLevel(method1, methodSubstitutor1, types2AtSite, languageLevel, false, varargsPosition);

View File

@@ -0,0 +1,22 @@
class Test {
public static <Tfoo, Vfoo> Future<Vfoo> foo(Future<Tfoo> future, Function<Tfoo, Vfoo> function) {
return future.map(function);
}
// These interfaces inspired by FoundationDB Java client class files
interface PartialFunction <TP, VP> {
VP apply(TP t) throws java.lang.Exception;
}
interface Function <TF, VF> extends PartialFunction<TF, VF> {
VF apply(TF t);
}
interface PartialFuture <TPP> {
<VPP> PartialFuture<VPP> map(PartialFunction<TPP, VPP> partialFunction);
}
interface Future <TFF> extends PartialFuture<TFF> {
<VFF> Future<VFF> map(Function<TFF, VFF> function);
}
}

View File

@@ -111,6 +111,10 @@ public class MostSpecificResolutionTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testIDEA127584() throws Exception {
doTest();
}
private void doTest() {
doTest(true);
}