method refs: site substitution should not replace session setup (IDEA-154722)

This commit is contained in:
Anna.Kozlova
2016-04-14 12:25:30 +02:00
parent d8e15274ef
commit f64bd14441
4 changed files with 48 additions and 15 deletions

View File

@@ -643,6 +643,12 @@ public class InferenceSession {
}
public InferenceVariable[] initBounds(PsiElement context, PsiTypeParameter... typeParameters) {
return initBounds(context, mySiteSubstitutor, typeParameters);
}
public InferenceVariable[] initBounds(PsiElement context,
final PsiSubstitutor siteSubstitutor,
PsiTypeParameter... typeParameters) {
List<InferenceVariable> result = new ArrayList<InferenceVariable>(typeParameters.length);
for (PsiTypeParameter parameter : typeParameters) {
String name = parameter.getName();
@@ -661,7 +667,7 @@ public class InferenceSession {
boolean added = false;
final PsiClassType[] extendsListTypes = parameter.getExtendsListTypes();
for (PsiType classType : extendsListTypes) {
classType = substituteWithInferenceVariables(mySiteSubstitutor.substitute(classType));
classType = substituteWithInferenceVariables(siteSubstitutor.substitute(classType));
if (isProperType(classType)) {
added = true;
}
@@ -1144,7 +1150,8 @@ public class InferenceSession {
if (lowerBound != PsiType.NULL && !TypeConversionUtil.isAssignable(eqBound, lowerBound)) {
final String incompatibleBoundsMessage =
incompatibleBoundsMessage(var, substitutor, InferenceBound.EQ, EQUALITY_CONSTRAINTS_PRESENTATION, InferenceBound.LOWER, LOWER_BOUNDS_PRESENTATION);
return registerIncompatibleErrorMessage(var, incompatibleBoundsMessage);
registerIncompatibleErrorMessage(incompatibleBoundsMessage);
return PsiType.NULL;
} else {
type = eqBound;
@@ -1169,7 +1176,8 @@ public class InferenceSession {
if (type instanceof PsiIntersectionType) {
final String conflictingConjunctsMessage = ((PsiIntersectionType)type).getConflictingConjunctsMessage();
if (conflictingConjunctsMessage != null) {
return registerIncompatibleErrorMessage(var, "Type parameter " + var.getParameter().getName() + " has incompatible upper bounds: " + conflictingConjunctsMessage);
registerIncompatibleErrorMessage("Type parameter " + var.getParameter().getName() + " has incompatible upper bounds: " + conflictingConjunctsMessage);
return PsiType.NULL;
}
}
}
@@ -1184,7 +1192,8 @@ public class InferenceSession {
incompatibleBoundsMessage = incompatibleBoundsMessage(var, substitutor, InferenceBound.LOWER, LOWER_BOUNDS_PRESENTATION, InferenceBound.UPPER, UPPER_BOUNDS_PRESENTATION);
}
if (incompatibleBoundsMessage != null) {
return registerIncompatibleErrorMessage(var, incompatibleBoundsMessage);
registerIncompatibleErrorMessage(incompatibleBoundsMessage);
return PsiType.NULL;
}
}
}
@@ -1196,11 +1205,6 @@ public class InferenceSession {
final PsiType substituted = myRestoreNameSubstitution.substitute(psiType);
return substituted != null ? substituted.getPresentableText() : null;
}
private PsiType registerIncompatibleErrorMessage(InferenceVariable var, @NotNull String incompatibleBoundsMessage) {
registerIncompatibleErrorMessage(incompatibleBoundsMessage);
return PsiType.NULL;
}
public void registerIncompatibleErrorMessage(Collection<InferenceVariable> variables, String incompatibleTypesMessage) {
variables = new ArrayList<InferenceVariable>(variables);
@@ -1938,10 +1942,6 @@ public class InferenceSession {
return null;
}
public void registerSiteSubstitutor(PsiSubstitutor substitutor) {
mySiteSubstitutor = mySiteSubstitutor.putAll(substitutor);
}
public List<String> getIncompatibleErrorMessages() {
return myErrorMessages;
}

View File

@@ -186,8 +186,7 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
LOG.assertTrue(interfaceClass != null);
if (PsiPolyExpressionUtil.mentionsTypeParameters(referencedMethodReturnType,
ContainerUtil.newHashSet(method.getTypeParameters()))) {
session.registerSiteSubstitutor(psiSubstitutor);
session.initBounds(myExpression, method.getTypeParameters());
session.initBounds(myExpression, psiSubstitutor, method.getTypeParameters());
//the constraint reduces to the bound set B3 which would be used to determine the method reference's invocation type
//when targeting the return type of the function type, as defined in 18.5.2.
session.collectApplicabilityConstraints(myExpression, ((MethodCandidateInfo)resolve), groundTargetType);

View File

@@ -0,0 +1,30 @@
import java.util.function.Function;
abstract class Result<V> {
public abstract <U> Result<U> map(Function<V, U> f);
public abstract <U> Result<U> flatMap(Function<V, Result<U>> f);
<B, C> void simplified(final Result<Function<B, C>> r, final Result<B> b1) {
Result<C> rr = r.flatMap(b1::map);
}
public static <A, B, C> Function<Result<A>, Function<Result<B>, Result<C>>> lift2(final Function<A, Function<B, C>> f) {
return a -> b -> a.map(f).flatMap(b::map);
}
public static <A, B, C> Function<Result<A>, Function<Result<B>, Result<C>>> lift2a(final Function<A, Function<B, C>> f) {
return a -> b -> a.map(f).flatMap((Function<B, Result<C>>) (f1) -> b.map<error descr="'map(java.util.function.Function<B,U>)' in 'Result' cannot be applied to '(B)'">(f1)</error>);
}
public static <A, B, C> Function<Result<A>, Function<Result<B>, Result<C>>> lift2b(final Function<A, Function<B, C>> f) {
return a -> b -> a.map(f).flatMap(f1 -> b.map(f1));
}
public static <A, B, C> Function<Result<A>, Function<Result<B>, Result<C>>> lift2c(final Function<A, Function<B, C>> f) {
return a -> b -> a.map(f).flatMap((Function<B, C> f1) -> b.map(f1));
}
}

View File

@@ -514,6 +514,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testChainedCallsWithMethodReferenceInside() throws Exception {
doTest();
}
private void doTest() {
doTest(false);
}