lambda: preserve partial substitutor data during substitute

This commit is contained in:
anna
2013-02-12 17:42:24 +01:00
parent c496660a79
commit b0a04ac5d2
6 changed files with 29 additions and 21 deletions
@@ -82,7 +82,16 @@ public class LambdaUtil {
final PsiClass methodContainingClass = method.getContainingClass();
LOG.assertTrue(methodContainingClass != null);
return TypeConversionUtil.getSuperClassSubstitutor(methodContainingClass, derivedClass, resolveResult.getSubstitutor());
PsiSubstitutor initialSubst = resolveResult.getSubstitutor();
final PsiSubstitutor superClassSubstitutor =
TypeConversionUtil.getSuperClassSubstitutor(methodContainingClass, derivedClass, PsiSubstitutor.EMPTY);
for (PsiTypeParameter param : superClassSubstitutor.getSubstitutionMap().keySet()) {
final PsiType substitute = superClassSubstitutor.substitute(param);
if (substitute != null) {
initialSubst = initialSubst.put(param, initialSubst.substitute(substitute));
}
}
return initialSubst;
}
public static boolean isValidLambdaContext(PsiElement context) {
@@ -310,7 +310,7 @@ public class PsiSubstitutorImpl implements PsiSubstitutor {
}
if (alreadyFound) continue;*/
final PsiType substituted = substituteInternal(original);
if (substituted == null) return false;
//if (substituted == null) return false;
substMap.put(param, substituted);
}
}
@@ -709,19 +709,16 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
final Pair<PsiType, ConstraintType> constraintFromFormalParams = inferConstraintFromLambdaFormalParams(typeParam, subst, method, lambdaExpression);
if (constraintFromFormalParams != null) return constraintFromFormalParams;
final PsiParameter[] methodParameters = method.getParameterList().getParameters();
if (methodParamsDependOn(typeParam, lambdaExpression, functionalInterfaceType, methodParameters, subst)) {
if (lowerBound != PsiType.NULL) {
return null;
}
return getFailedInferenceConstraint(typeParam);
}
final Set<PsiParameterList> lists = LambdaUtil.ourParams.get();
if (lists != null && lists.contains(lambdaExpression.getParameterList())){
return null;
}
final PsiParameter[] methodParameters = method.getParameterList().getParameters();
if (methodParamsDependOn(typeParam, lambdaExpression, functionalInterfaceType, methodParameters, subst)) {
return null;
}
final PsiType returnType = subst.substitute(method.getReturnType());
if (returnType != null && returnType != PsiType.VOID) {
Pair<PsiType, ConstraintType> constraint = null;
@@ -985,8 +982,11 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
constraint = policy.inferTypeConstraintFromCallContext(methodCall, (PsiExpressionList)parent, (PsiCallExpression)pParent, typeParameter);
if (constraint == null && PsiUtil.isLanguageLevel8OrHigher(methodCall)) {
constraint = graphInferenceFromCallContext(methodCall, typeParameter, (PsiCallExpression)pParent);
if (constraint != null && constraint.getFirst().equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
constraint = null;
if (constraint != null) {
final PsiType constraintFirst = constraint.getFirst();
if (constraintFirst == null || constraintFirst.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
constraint = null;
}
}
}
}
@@ -1057,10 +1057,9 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
}
}
final PsiSubstitutor finalSubstitutor = substitutor.put(typeParameter, null);
PsiClassType[] superTypes = typeParameter.getSuperTypes();
if (superTypes.length == 0) return null;
PsiType superType = finalSubstitutor.substitute(superTypes[0]);
PsiType superType = TypeConversionUtil.erasure(superTypes[0]);
if (superType == null) superType = PsiType.getJavaLangObject(manager, scope);
if (superType == null) return null;
return policy.getInferredTypeWithNoConstraint(manager, superType);
@@ -1094,7 +1093,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
return result;
}
private static RecursionGuard ourGraphGuard = RecursionManager.createGuard("typeArgInference");
private static RecursionGuard ourGraphGuard = RecursionManager.createGuard("graphTypeArgInference");
private static Pair<PsiType, ConstraintType> graphInferenceFromCallContext(@NotNull final PsiExpression methodCall,
@NotNull final PsiTypeParameter typeParameter,
@NotNull final PsiCallExpression parentCall) {
@@ -22,7 +22,7 @@ class InferenceFromArgs {
bar(b, (k, v) -> {Integer i = k; return v;});
bazz(<error descr="Cyclic inference">(k, v) -> v</error>);
bazz((k, v) -> {<error descr="Incompatible types. Found: '<lambda parameter>', required: 'int'">int i = k;</error> return v;});
bazz((k, v) -> {<error descr="Incompatible types. Found: 'java.lang.Object', required: 'int'">int i = k;</error> return v;});
}
public static <T> SameArgsI<T> max() {
@@ -57,7 +57,7 @@ class ReturnTypeCompatibility {
}
public static void main(String[] args) {
<error descr="Cannot resolve method 'call(<lambda expression>)'">call</error>(i-> {return i;});
call<error descr="Ambiguous method call: both 'ReturnTypeCompatibility.call(I1)' and 'ReturnTypeCompatibility.call(I2)' match">(i-> {return i;})</error>;
}
}
@@ -29,8 +29,8 @@ class TypeArgsConsistency1 {
{
I<Integer> i1 = (i, j) -> i + j;
foo((i, j) -> i + j);
I<Integer> i2 =bar(<error descr="Cyclic inference">(i, j) -> i</error>) ;
I<Integer> i3 = bar(<error descr="Cyclic inference">(i, j) -> "" + i + j</error>);
I<Integer> i2 =bar((i, j) -> i) ;
I<Integer> i3 = bar(<error descr="Incompatible return type String in lambda expression">(i, j) -> "" + i + j</error>);
}
}
@@ -40,8 +40,8 @@ class TypeArgsConsistency2 {
static <T> I2<T> bar2(I2<T> i) {return i;}
public static void main(String[] args) {
I<Integer> i1 = bar(<error descr="Cyclic inference">x -> x</error>);
I1<Integer> i2 = bar1(<error descr="Cyclic inference">x -> 1</error>);
I<Integer> i1 = bar(x -> x);
I1<Integer> i2 = bar1(x -> 1);
I2<String> aI2 = bar2(x -> "");
<error descr="Incompatible types. Found: 'TypeArgsConsistency2.I2<java.lang.String>', required: 'TypeArgsConsistency2.I2<java.lang.Integer>'">I2<Integer> aI28 = bar2( x-> "");</error>
I2<Integer> i3 = bar2(x -> x);