mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-05 01:50:56 +07:00
overload resolution: reject more specific inference contradicting site substitution
This commit is contained in:
@@ -1335,6 +1335,7 @@ public class InferenceSession {
|
||||
*/
|
||||
public static boolean isMoreSpecific(PsiMethod m1,
|
||||
PsiMethod m2,
|
||||
PsiSubstitutor siteSubstitutor1,
|
||||
PsiExpression[] args,
|
||||
PsiElement context,
|
||||
boolean varargs) {
|
||||
@@ -1342,7 +1343,10 @@ public class InferenceSession {
|
||||
for (PsiTypeParameter param : PsiUtil.typeParametersIterable(m2)) {
|
||||
params.add(param);
|
||||
}
|
||||
final InferenceSession session = new InferenceSession(params.toArray(new PsiTypeParameter[params.size()]), PsiSubstitutor.EMPTY, m2.getManager(), context);
|
||||
|
||||
siteSubstitutor1 = getSiteSubstitutor(siteSubstitutor1, params);
|
||||
|
||||
final InferenceSession session = new InferenceSession(params.toArray(new PsiTypeParameter[params.size()]), siteSubstitutor1, m2.getManager(), context);
|
||||
|
||||
final PsiParameter[] parameters1 = m1.getParameterList().getParameters();
|
||||
final PsiParameter[] parameters2 = m2.getParameterList().getParameters();
|
||||
@@ -1352,8 +1356,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, PsiSubstitutor.EMPTY, false);
|
||||
PsiType tType = session.substituteWithInferenceVariables(getParameterType(parameters2, i, PsiSubstitutor.EMPTY, varargs));
|
||||
PsiType sType = getParameterType(parameters1, i, siteSubstitutor1, false);
|
||||
PsiType tType = session.substituteWithInferenceVariables(getParameterType(parameters2, i, siteSubstitutor1, varargs));
|
||||
if (LambdaUtil.isFunctionalType(sType) && LambdaUtil.isFunctionalType(tType) && !relates(sType, tType)) {
|
||||
if (!isFunctionalTypeMoreSpecific(sType, tType, session, args[i])) {
|
||||
return false;
|
||||
@@ -1369,14 +1373,22 @@ public class InferenceSession {
|
||||
}
|
||||
|
||||
if (varargs) {
|
||||
PsiType sType = getParameterType(parameters1, paramsLength, PsiSubstitutor.EMPTY, true);
|
||||
PsiType tType = session.substituteWithInferenceVariables(getParameterType(parameters2, paramsLength, PsiSubstitutor.EMPTY, true));
|
||||
PsiType sType = getParameterType(parameters1, paramsLength, siteSubstitutor1, true);
|
||||
PsiType tType = session.substituteWithInferenceVariables(getParameterType(parameters2, paramsLength, siteSubstitutor1, true));
|
||||
session.addConstraint(new StrictSubtypingConstraint(tType, sType));
|
||||
}
|
||||
|
||||
return session.repeatInferencePhases(true);
|
||||
}
|
||||
|
||||
private static PsiSubstitutor getSiteSubstitutor(PsiSubstitutor siteSubstitutor1, List<PsiTypeParameter> params) {
|
||||
PsiSubstitutor subst = PsiSubstitutor.EMPTY;
|
||||
for (PsiTypeParameter param : params) {
|
||||
subst = subst.put(param, siteSubstitutor1.substitute(param));
|
||||
}
|
||||
return subst;
|
||||
}
|
||||
|
||||
/**
|
||||
* 15.12.2.5 Choosing the Most Specific Method
|
||||
* "a functional interface type S is more specific than a functional interface type T for an expression exp" part
|
||||
|
||||
@@ -544,10 +544,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);
|
||||
boolean applicable12 = isApplicableTo(types2AtSite, method1, languageLevel, varargsPosition, methodSubstitutor1, method2, siteSubstitutor2);
|
||||
|
||||
final PsiSubstitutor methodSubstitutor2 = calculateMethodSubstitutor(typeParameters2, method2, siteSubstitutor2, types2, types1AtSite, languageLevel);
|
||||
boolean applicable21 = isApplicableTo(types1AtSite, method2, languageLevel, varargsPosition, methodSubstitutor2, method1);
|
||||
boolean applicable21 = isApplicableTo(types1AtSite, method2, languageLevel, varargsPosition, methodSubstitutor2, method1, siteSubstitutor1);
|
||||
|
||||
if (!myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
|
||||
final boolean typeArgsApplicable12 = GenericsUtil.isTypeArgumentsApplicable(typeParameters1, methodSubstitutor1, myArgumentsList, !applicable21);
|
||||
@@ -641,11 +641,12 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
|
||||
@NotNull LanguageLevel languageLevel,
|
||||
boolean varargsPosition,
|
||||
@NotNull PsiSubstitutor methodSubstitutor1,
|
||||
@NotNull PsiMethod method2) {
|
||||
@NotNull PsiMethod method2,
|
||||
PsiSubstitutor siteSubstitutor1) {
|
||||
if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && method1.getTypeParameters().length > 0 && myArgumentsList instanceof PsiExpressionList) {
|
||||
final PsiElement parent = myArgumentsList.getParent();
|
||||
if (parent instanceof PsiCallExpression) {
|
||||
return InferenceSession.isMoreSpecific(method2, method1, ((PsiExpressionList)myArgumentsList).getExpressions(), myArgumentsList, varargsPosition);
|
||||
return InferenceSession.isMoreSpecific(method2, method1, siteSubstitutor1, ((PsiExpressionList)myArgumentsList).getExpressions(), myArgumentsList, varargsPosition);
|
||||
}
|
||||
}
|
||||
final PsiUtil.ApplicabilityChecker applicabilityChecker = languageLevel.isAtLeast(LanguageLevel.JDK_1_8)
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
class Test {
|
||||
interface One<T> {
|
||||
<S extends T> S save(S entity);
|
||||
<S extends T> Iterable<S> save(Iterable<S> entities);
|
||||
}
|
||||
static One<String> foo;
|
||||
public static void main(String[] args) throws Exception {
|
||||
foo.save <error descr="Ambiguous method call: both 'One.save(String)' and 'One.save(Iterable<String>)' match">(null)</error>;
|
||||
}
|
||||
}
|
||||
@@ -126,6 +126,10 @@ public class MostSpecificResolutionTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
public void testIncompatibleSiteSubstitutionBounds() throws Exception {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(true);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user