new inference: exclude return constraints/non pertinent to applicability argument constraints from overload resolution process

This commit is contained in:
Anna Kozlova
2014-02-11 09:40:00 +01:00
parent b9ef7b60c7
commit 4889751ded
5 changed files with 38 additions and 24 deletions
@@ -111,7 +111,7 @@ public class MethodCandidateInfo extends CandidateInfo{
return ApplicabilityLevel.NOT_APPLICABLE;
}
else {
final PsiSubstitutor substitutor = getSubstitutor();
final PsiSubstitutor substitutor = getSubstitutor(false);
Integer boxedLevel = ourOverloadGuard.doPreventingRecursion(myArgumentList, false, new Computable<Integer>() {
@Override
public Integer compute() {
@@ -120,7 +120,7 @@ public class MethodCandidateInfo extends CandidateInfo{
});
level = boxedLevel != null ? boxedLevel : getApplicabilityLevel();
}
if (level > ApplicabilityLevel.NOT_APPLICABLE && !isTypeArgumentsApplicable()) level = ApplicabilityLevel.NOT_APPLICABLE;
if (level > ApplicabilityLevel.NOT_APPLICABLE && !isTypeArgumentsApplicable(false)) level = ApplicabilityLevel.NOT_APPLICABLE;
return level;
}
Integer boxedLevel = ourOverloadGuard.doPreventingRecursion(myArgumentList, false, new Computable<Integer>() {
@@ -145,7 +145,7 @@ public class MethodCandidateInfo extends CandidateInfo{
@NotNull
public PsiSubstitutor getSubstitutor(boolean includeReturnConstraint) {
PsiSubstitutor substitutor = myCalcedSubstitutor;
if (substitutor == null || !includeReturnConstraint) {
if (substitutor == null || !includeReturnConstraint && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
PsiSubstitutor incompleteSubstitutor = super.getSubstitutor();
PsiMethod method = getElement();
if (myTypeArguments == null) {
@@ -153,7 +153,7 @@ public class MethodCandidateInfo extends CandidateInfo{
final PsiSubstitutor inferredSubstitutor = inferTypeArguments(DefaultParameterTypeInferencePolicy.INSTANCE, includeReturnConstraint);
if (!stackStamp.mayCacheNow() || !includeReturnConstraint) {
if (!stackStamp.mayCacheNow() || !includeReturnConstraint && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
return inferredSubstitutor;
}
@@ -173,12 +173,16 @@ public class MethodCandidateInfo extends CandidateInfo{
public boolean isTypeArgumentsApplicable() {
return isTypeArgumentsApplicable(false);
}
public boolean isTypeArgumentsApplicable(boolean includeReturnConstraint) {
final PsiMethod psiMethod = getElement();
PsiTypeParameter[] typeParams = psiMethod.getTypeParameters();
if (myTypeArguments != null && typeParams.length != myTypeArguments.length && !PsiUtil.isLanguageLevel7OrHigher(psiMethod)){
return typeParams.length == 0 && JavaVersionService.getInstance().isAtLeast(psiMethod, JavaSdkVersion.JDK_1_7);
}
PsiSubstitutor substitutor = getSubstitutor();
PsiSubstitutor substitutor = getSubstitutor(includeReturnConstraint);
return GenericsUtil.isTypeArgumentsApplicable(typeParams, substitutor, getParent());
}
@@ -199,10 +199,19 @@ public class InferenceSession {
@Nullable PsiExpression[] args,
@Nullable PsiElement parent,
ParameterTypeInferencePolicy policy) {
boolean doesNotContainFalseBound = repeatInferencePhases(parameters == null);
return infer(parameters, args, parent, false, policy);
}
@NotNull
public PsiSubstitutor infer(@Nullable PsiParameter[] parameters,
@Nullable PsiExpression[] args,
@Nullable PsiElement parent,
boolean acceptNonPertinentArgs,
ParameterTypeInferencePolicy policy) {
boolean doesNotContainFalseBound = repeatInferencePhases(parameters == null || !policy.allowPostponeInference());
// if (!doesNotContainFalseBound) return prepareSubstitution();
resolveBounds(myInferenceVariables.values(), mySiteSubstitutor, false);
resolveBounds(myInferenceVariables.values(), mySiteSubstitutor, !policy.allowPostponeInference());
final Pair<PsiMethod, PsiCallExpression> pair = getPair(parent);
if (pair != null) {
@@ -220,7 +229,7 @@ public class InferenceSession {
MethodCandidateInfo.updateSubstitutor(argumentList, substitutor);
}
if (parameters != null && args != null) {
if (parameters != null && args != null && (acceptNonPertinentArgs || pair != null)) {
final Set<ConstraintFormula> additionalConstraints = new HashSet<ConstraintFormula>();
if (parameters.length > 0) {
for (int i = 0; i < args.length; i++) {
@@ -112,7 +112,7 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
final PsiExpression[] args = argumentList.getExpressions();
final PsiParameter[] parameters = method.getParameterList().getParameters();
callSession.initExpressionConstraints(parameters, args, myExpression, method);
substitutor = callSession.infer(parameters, args, myExpression, LiftParameterTypeInferencePolicy.INSTANCE);
substitutor = callSession.infer(parameters, args, myExpression, true, LiftParameterTypeInferencePolicy.INSTANCE);
}
} else {
substitutor = pair.second;
@@ -123,7 +123,8 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
if (methodParameters.length == 0) continue;
final PsiParameter param = i < methodParameters.length ? methodParameters[i] : methodParameters[methodParameters.length - 1];
final PsiType paramType = param.getType();
if (!LambdaUtil.isAcceptable(lambdaExpression, conflict.getSubstitutor().substitute(paramType), lambdaExpression.hasFormalParameterTypes())) {
if (!LambdaUtil.isAcceptable(lambdaExpression, ((MethodCandidateInfo)conflict).getSubstitutor(false).substitute(paramType),
lambdaExpression.hasFormalParameterTypes())) {
iterator.remove();
}
}
@@ -147,7 +148,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
ProgressManager.checkCanceled();
final CandidateInfo conflict = newConflictsArray[j];
if (nonComparable(method, conflict)) continue;
switch (isMoreSpecific(method, conflict, applicabilityLevel, languageLevel)) {
switch (isMoreSpecific((MethodCandidateInfo)method, (MethodCandidateInfo)conflict, applicabilityLevel, languageLevel)) {
case FIRST:
conflicts.remove(conflict);
break;
@@ -217,7 +218,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
}
PsiClass class1 = method.getContainingClass();
PsiSubstitutor infoSubstitutor = info.getSubstitutor();
PsiSubstitutor infoSubstitutor = ((MethodCandidateInfo)info).getSubstitutor(false);
MethodSignature signature = method.getSignature(infoSubstitutor);
CandidateInfo existing = signatures.get(signature);
@@ -276,7 +277,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
PsiType returnType2 = existingMethod.getReturnType();
if (returnType1 != null && returnType2 != null) {
returnType1 = infoSubstitutor.substitute(returnType1);
returnType2 = existing.getSubstitutor().substitute(returnType2);
returnType2 = ((MethodCandidateInfo)existing).getSubstitutor(false).substitute(returnType2);
if (!returnType1.equals(returnType2) && returnType1.isAssignableFrom(returnType2)) {
conflicts.remove(i);
i--;
@@ -437,12 +438,12 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
return TypeConversionUtil.boxingConversionApplicable(parameterType, argType);
}
private Specifics isMoreSpecific(final CandidateInfo info1,
final CandidateInfo info2,
private Specifics isMoreSpecific(final MethodCandidateInfo info1,
final MethodCandidateInfo info2,
@MethodCandidateInfo.ApplicabilityLevelConstant int applicabilityLevel,
@NotNull LanguageLevel languageLevel) {
PsiMethod method1 = (PsiMethod)info1.getElement();
PsiMethod method2 = (PsiMethod)info2.getElement();
PsiMethod method1 = info1.getElement();
PsiMethod method2 = info2.getElement();
final PsiClass class1 = method1.getContainingClass();
final PsiClass class2 = method2.getContainingClass();
@@ -451,8 +452,8 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
final PsiTypeParameter[] typeParameters1 = method1.getTypeParameters();
final PsiTypeParameter[] typeParameters2 = method2.getTypeParameters();
final PsiSubstitutor classSubstitutor1 = info1.getSubstitutor(); //substitutions for method type parameters will be ignored
final PsiSubstitutor classSubstitutor2 = info2.getSubstitutor();
final PsiSubstitutor classSubstitutor1 = info1.getSubstitutor(false); //substitutions for method type parameters will be ignored
final PsiSubstitutor classSubstitutor2 = info2.getSubstitutor(false);
final int max = Math.max(params1.length, params2.length);
PsiType[] types1 = PsiType.createArray(max);
@@ -504,8 +505,8 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
if (boxingHappened[0] > 0 && boxingHappened[1] == 0) return Specifics.SECOND;
if (sameBoxing) {
final PsiSubstitutor siteSubstitutor1 = ((MethodCandidateInfo)info1).getSiteSubstitutor();
final PsiSubstitutor siteSubstitutor2 = ((MethodCandidateInfo)info2).getSiteSubstitutor();
final PsiSubstitutor siteSubstitutor1 = info1.getSiteSubstitutor();
final PsiSubstitutor siteSubstitutor2 = info2.getSiteSubstitutor();
final PsiType[] types2AtSite = typesAtSite(types2, siteSubstitutor2, typeParameters2);
final PsiType[] types1AtSite = typesAtSite(types1, siteSubstitutor1, typeParameters1);
@@ -607,7 +608,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
if (class1 != class2) {
if (class2.isInheritor(class1, true) || class1.isInterface() && !class2.isInterface()) {
if (MethodSignatureUtil.isSubsignature(method1.getSignature(info1.getSubstitutor()), method2.getSignature(info2.getSubstitutor()))) {
if (MethodSignatureUtil.isSubsignature(method1.getSignature(info1.getSubstitutor(false)), method2.getSignature(info2.getSubstitutor(false)))) {
return Specifics.SECOND;
}
else if (method1.hasModifierProperty(PsiModifier.STATIC) && method2.hasModifierProperty(PsiModifier.STATIC) && boxingHappened[0] == 0) {
@@ -616,7 +617,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
}
else if (class1.isInheritor(class2, true) || class2.isInterface()) {
if (MethodSignatureUtil.areErasedParametersEqual(method1.getSignature(PsiSubstitutor.EMPTY), method2.getSignature(PsiSubstitutor.EMPTY)) &&
MethodSignatureUtil.isSubsignature(method2.getSignature(info2.getSubstitutor()), method1.getSignature(info1.getSubstitutor()))) {
MethodSignatureUtil.isSubsignature(method2.getSignature(info2.getSubstitutor(false)), method1.getSignature(info1.getSubstitutor(false)))) {
return Specifics.FIRST;
}
else if (method1.hasModifierProperty(PsiModifier.STATIC) && method2.hasModifierProperty(PsiModifier.STATIC) && boxingHappened[0] == 0) {
@@ -25,7 +25,7 @@ class ReturnTypeIncompatibility {
}
public static void main(String[] args) {
call<error descr="Ambiguous method call: both 'ReturnTypeIncompatibility.call(I1<Integer>)' and 'ReturnTypeIncompatibility.call(I3<Object>)' match">(i-> {return i;})</error>;
call<error descr="Ambiguous method call: both 'ReturnTypeIncompatibility.call(I1<Integer>)' and 'ReturnTypeIncompatibility.call(I2<Integer>)' match">(i-> {return i;})</error>;
}
}