java: prohibit caching when using thread-local types imposed on expressions and decla...
authorpeter <peter@jetbrains.com>
Mon, 27 May 2019 05:55:38 +0000 (07:55 +0200)
committerintellij-monorepo-bot <intellij-monorepo-bot-no-reply@jetbrains.com>
Mon, 27 May 2019 06:04:05 +0000 (09:04 +0300)
GitOrigin-RevId: a767826dedb5d1879009ee5804e1c675d1b863ac

13 files changed:
java/java-psi-api/src/com/intellij/psi/LambdaUtil.java
java/java-psi-api/src/com/intellij/psi/ThreadLocalTypes.java [new file with mode: 0644]
java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java
java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java
java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java
java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java
java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguitySpecificReturn.java
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/overloadResolution/IDEA102800.java
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/overloadResolution/VoidValueCompatibilityOfImplicitlyTypedLambda.java

index 58cc208d2123efd578d53782a558568e6aa37833..146b86c00a6cb822513bb3e324a64a954c0c88e9 100644 (file)
@@ -23,7 +23,6 @@ import java.util.function.Supplier;
  * @author anna
  */
 public class LambdaUtil {
-  private static final ThreadLocal<Map<PsiElement, PsiType>> ourFunctionTypes = new ThreadLocal<>();
   private static final Logger LOG = Logger.getInstance(LambdaUtil.class);
 
   @Nullable
@@ -355,12 +354,10 @@ public class LambdaUtil {
       parent = parent.getParent();
     }
 
-    final Map<PsiElement, PsiType> map = ourFunctionTypes.get();
-    if (map != null) {
-      final PsiType type = ObjectUtils.chooseNotNull(map.get(expression), map.get(element));
-      if (type != null) {
-        return type;
-      }
+    PsiType type = ThreadLocalTypes.getElementType(expression);
+    if (type == null) type = ThreadLocalTypes.getElementType(element);
+    if (type != null) {
+      return type;
     }
 
     if (parent instanceof PsiArrayInitializerExpression) {
@@ -648,16 +645,6 @@ public class LambdaUtil {
     return false;
   }
 
-  @NotNull
-  public static Map<PsiElement, PsiType> getFunctionalTypeMap() {
-    Map<PsiElement, PsiType> map = ourFunctionTypes.get();
-    if (map == null) {
-      map = new HashMap<>();
-      ourFunctionTypes.set(map);
-    }
-    return map;
-  }
-
   public static Map<PsiElement, String> checkReturnTypeCompatible(PsiLambdaExpression lambdaExpression, PsiType functionalInterfaceReturnType) {
     Map<PsiElement, String> errors = new LinkedHashMap<>();
     if (PsiType.VOID.equals(functionalInterfaceReturnType)) {
@@ -751,7 +738,7 @@ public class LambdaUtil {
             break;
           }
 
-          if (getFunctionalTypeMap().containsKey(lambdaExpression)) {
+          if (ThreadLocalTypes.hasBindingFor(lambdaExpression)) {
             break;
           }
         }
@@ -761,7 +748,7 @@ public class LambdaUtil {
         break;
       }
 
-      if (parent instanceof PsiLambdaExpression && getFunctionalTypeMap().containsKey(parent)) {
+      if (parent instanceof PsiLambdaExpression && ThreadLocalTypes.hasBindingFor(parent)) {
         break;
       }
 
@@ -770,7 +757,7 @@ public class LambdaUtil {
         break;
       }
       if (MethodCandidateInfo.isOverloadCheck(psiCall.getArgumentList()) ||
-          lambdaExpression != null && getFunctionalTypeMap().containsKey(lambdaExpression)) {
+          lambdaExpression != null && ThreadLocalTypes.hasBindingFor(lambdaExpression)) {
         break;
       }
 
@@ -834,7 +821,7 @@ public class LambdaUtil {
   public static <T> T performWithSubstitutedParameterBounds(final PsiTypeParameter[] typeParameters,
                                                             final PsiSubstitutor substitutor,
                                                             final Supplier<? extends T> producer) {
-    try {
+    return ThreadLocalTypes.performWithTypes(map -> {
       for (PsiTypeParameter parameter : typeParameters) {
         final PsiClassType[] types = parameter.getExtendsListTypes();
         if (types.length > 0) {
@@ -842,31 +829,18 @@ public class LambdaUtil {
           //don't glb to avoid flattening = Object&Interface would be preserved
           //otherwise methods with different signatures could get same erasure
           final PsiType upperBound = PsiIntersectionType.createIntersection(false, conjuncts.toArray(PsiType.EMPTY_ARRAY));
-          getFunctionalTypeMap().put(parameter, upperBound);
+          map.forceType(parameter, upperBound);
         }
       }
       return producer.get();
-    }
-    finally {
-      for (PsiTypeParameter parameter : typeParameters) {
-        getFunctionalTypeMap().remove(parameter);
-      }
-    }
+    });
   }
 
   public static <T> T performWithTargetType(@NotNull PsiElement element, @NotNull PsiType targetType, @NotNull Supplier<? extends T> producer) {
-    Map<PsiElement, PsiType> map = getFunctionalTypeMap();
-    PsiType prev = map.put(element, targetType);
-    try {
+    return ThreadLocalTypes.performWithTypes(types -> {
+      types.forceType(element, targetType);
       return producer.get();
-    }
-    finally {
-      if (prev == null) {
-        map.remove(element);
-      } else {
-        map.put(element, prev);
-      }
-    }
+    });
   }
 
   /**
diff --git a/java/java-psi-api/src/com/intellij/psi/ThreadLocalTypes.java b/java/java-psi-api/src/com/intellij/psi/ThreadLocalTypes.java
new file mode 100644 (file)
index 0000000..df99cde
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.psi;
+
+import com.intellij.openapi.util.RecursionGuard;
+import com.intellij.openapi.util.RecursionManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+public class ThreadLocalTypes {
+  private static final RecursionGuard<ThreadLocalTypes> ourGuard = RecursionManager.createGuard("ThreadLocalTypes");
+  private final Map<PsiElement, PsiType> myMap = new HashMap<>();
+
+  private ThreadLocalTypes() {}
+
+  @Nullable
+  public static PsiType getElementType(@NotNull PsiElement psi) {
+    List<? extends ThreadLocalTypes> stack = ourGuard.currentStack();
+    for (int i = stack.size() - 1; i >= 0; i--) {
+      ThreadLocalTypes types = stack.get(i);
+      PsiType type = types.myMap.get(psi);
+      if (type != null) {
+        ourGuard.prohibitResultCaching(types);
+        return type;
+      }
+    }
+    return null;
+  }
+
+  public static boolean hasBindingFor(@NotNull PsiElement psi) {
+    List<? extends ThreadLocalTypes> stack = ourGuard.currentStack();
+    for (int i = stack.size() - 1; i >= 0; i--) {
+      ThreadLocalTypes types = stack.get(i);
+      if (types.myMap.containsKey(psi)) {
+        ourGuard.prohibitResultCaching(types);
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public static <T> T performWithTypes(@NotNull Function<ThreadLocalTypes, T> action) {
+    ThreadLocalTypes types = new ThreadLocalTypes();
+    return ourGuard.doPreventingRecursion(types, false, () -> action.apply(types));
+  }
+
+  public void forceType(@NotNull PsiElement psi, @Nullable PsiType type) {
+    myMap.put(psi, type);
+  }
+
+}
index f08e56ea12cdcef36635d62a77c270199550dd04..693c091e9fb16fdae6f0807a7e661113485e403a 100644 (file)
@@ -35,7 +35,6 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Arrays;
-import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -183,21 +182,15 @@ public class MethodCandidateInfo extends CandidateInfo{
         .map(expression -> PsiUtil.skipParenthesizedExprDown(expression))
         .filter(expression -> expression != null && !(expression instanceof PsiFunctionalExpression))
         .toArray(PsiExpression[]::new);
-      Map<PsiElement, PsiType> expressionTypes = LambdaUtil.getFunctionalTypeMap();
-      try {
+      return ThreadLocalTypes.performWithTypes(expressionTypes -> {
         PsiMethod method = getElement();
         boolean varargs = isVarargs();
         for (PsiExpression context : expressions) {
-          expressionTypes.put(context,
-                              PsiTypesUtil.getTypeByMethod(context, argumentList, method, varargs, substitutor, false));
+          expressionTypes.forceType(context,
+                                    PsiTypesUtil.getTypeByMethod(context, argumentList, method, varargs, substitutor, false));
         }
         return computable.compute();
-      }
-      finally {
-        for (PsiExpression context : expressions) {
-          expressionTypes.remove(context);
-        }
-      }
+      });
     }
     else {
       return computable.compute();
index f1c3a3655f18bdc0f35904fab5decd4e5f6cde71..e5bccd1a8624cfa07e09f6602c7fc933c8f030c4 100644 (file)
@@ -987,7 +987,7 @@ public class PsiClassImplUtil {
     }
     PsiType upperBound = psiClass instanceof PsiTypeParameter ? TypeConversionUtil.getInferredUpperBoundForSynthetic((PsiTypeParameter)psiClass) : null;
     if (upperBound == null && psiClass instanceof PsiTypeParameter) {
-      upperBound = LambdaUtil.getFunctionalTypeMap().get(psiClass);
+      upperBound = ThreadLocalTypes.getElementType(psiClass);
     }
     if (upperBound instanceof PsiIntersectionType) {
       final PsiType[] conjuncts = ((PsiIntersectionType)upperBound).getConjuncts();
@@ -1030,7 +1030,7 @@ public class PsiClassImplUtil {
     }
     PsiType upperBound = psiClass instanceof PsiTypeParameter ? TypeConversionUtil.getInferredUpperBoundForSynthetic((PsiTypeParameter)psiClass) : null;
     if (upperBound == null && psiClass instanceof PsiTypeParameter) {
-      upperBound = LambdaUtil.getFunctionalTypeMap().get(psiClass);
+      upperBound = ThreadLocalTypes.getElementType(psiClass);
     }
     if (upperBound instanceof PsiIntersectionType) {
       final PsiType[] conjuncts = ((PsiIntersectionType)upperBound).getConjuncts();
index e09fa4ef8ff5bb322beeca08f7027f73cd84d3ad..6acc1393a93af0c2610356edbf7abba5f9f26338 100644 (file)
@@ -778,7 +778,7 @@ public class PsiImplUtil {
     }
     if (element instanceof PsiMethodReferenceExpression) {
       // method refs: do not cache results during parent conflict resolving, acceptable checks, etc
-      if (LambdaUtil.getFunctionalTypeMap().containsKey(element)) {
+      if (ThreadLocalTypes.hasBindingFor(element)) {
         return (JavaResolveResult[])resolver.resolve(element, psiFile, incompleteCode);
       }
     }
index 344ea4c9791278510e7baacd65ab42529ef22d12..ca1b61cf7e1d29036f292caf88e345bf7dd62c91 100644 (file)
@@ -54,6 +54,7 @@ public class InferenceSession {
   private PsiSubstitutor myInferenceSubstitution = PsiSubstitutor.EMPTY;
   private PsiSubstitutor myRestoreNameSubstitution = PsiSubstitutor.EMPTY;
   private MethodCandidateInfo myCurrentMethod;
+  private ThreadLocalTypes myTempTypes;
 
   public InferenceSession(InitialInferenceState initialState, ParameterTypeInferencePolicy policy) {
     myContext = initialState.getContext();
@@ -303,24 +304,22 @@ public class InferenceSession {
                                                  @Nullable PsiElement parent,
                                                  @Nullable MethodCandidateInfo currentMethod,
                                                  @NotNull PsiSubstitutor initialSubstitutor) {
-    try {
-      doInfer(parameters, args, parent, currentMethod, initialSubstitutor);
-      return prepareSubstitution();
-    }
-    finally {
-      for (ConstraintFormula formula : myConstraintsCopy) {
-        if (formula instanceof InputOutputConstraintFormula) {
-          LambdaUtil.getFunctionalTypeMap().remove(((InputOutputConstraintFormula)formula).getExpression());
-        }
-      }
-
-      if (currentMethod != null) {
-        if (myErrorMessages != null) {
-          currentMethod.setApplicabilityError(StringUtil.join(myErrorMessages, "\n"));
+    return ThreadLocalTypes.performWithTypes(types -> {
+      myTempTypes = types;
+      try {
+        doInfer(parameters, args, parent, currentMethod, initialSubstitutor);
+        return prepareSubstitution();
+      }
+      finally {
+        if (currentMethod != null) {
+          if (myErrorMessages != null) {
+            currentMethod.setApplicabilityError(StringUtil.join(myErrorMessages, "\n"));
+          }
+          currentMethod.setErased(myErased);
         }
-        currentMethod.setErased(myErased);
+        myTempTypes = null;
       }
-    }
+    });
   }
 
   private void doInfer(@Nullable PsiParameter[] parameters,
@@ -376,7 +375,7 @@ public class InferenceSession {
   }
 
   private static boolean isPertinentToApplicabilityCheckOnContainingCall(@NotNull PsiElement parent) {
-    return LambdaUtil.getFunctionalTypeMap().containsKey(parent);
+    return ThreadLocalTypes.hasBindingFor(parent);
   }
 
   private void collectAdditionalConstraints(PsiParameter[] parameters,
@@ -791,7 +790,7 @@ public class InferenceSession {
         final PsiExpressionList argumentList = ((PsiCall)gParent).getArgumentList();
         if (argumentList != null) {
           if (MethodCandidateInfo.isOverloadCheck(argumentList)) {
-            return LambdaUtil.getFunctionalTypeMap().get(context);
+            return ThreadLocalTypes.getElementType(context);
           }
 
           final JavaResolveResult result = PsiDiamondType.getDiamondsAwareResolveResult((PsiCall)gParent);
@@ -836,7 +835,7 @@ public class InferenceSession {
       //at this time, types of interface method parameter types must be already calculated
       // that's why walkUp in InferenceSessionContainer stops at this point and
       //that's why we can reuse this type here
-      final PsiType cachedLambdaType = LambdaUtil.getFunctionalTypeMap().get(lambdaExpression);
+      PsiType cachedLambdaType = ThreadLocalTypes.getElementType(lambdaExpression);
       if (cachedLambdaType != null) {
         return LambdaUtil.getFunctionalInterfaceReturnType(lambdaExpression.getGroundTargetType(cachedLambdaType));
       }
@@ -1386,6 +1385,10 @@ public class InferenceSession {
                                        PsiSubstitutor substitutor, 
                                        Set<ConstraintFormula> ignoredConstraints) {
     formula.apply(substitutor, true);
+    if (formula instanceof InputOutputConstraintFormula) {
+      myTempTypes.forceType(((InputOutputConstraintFormula)formula).getExpression(),
+                            ((InputOutputConstraintFormula)formula).getCurrentType());
+    }
 
     addConstraint(formula);
     if (!repeatInferencePhases()) {
@@ -1395,7 +1398,7 @@ public class InferenceSession {
     if (formula instanceof ExpressionCompatibilityConstraint) {
       PsiExpression expression = ((ExpressionCompatibilityConstraint)formula).getExpression();
       if (expression instanceof PsiLambdaExpression) {
-        PsiType parameterType = ((PsiLambdaExpression)expression).getGroundTargetType(((ExpressionCompatibilityConstraint)formula).getT());
+        PsiType parameterType = ((PsiLambdaExpression)expression).getGroundTargetType(((ExpressionCompatibilityConstraint)formula).getCurrentType());
         collectLambdaReturnExpression(additionalConstraints, ignoredConstraints, (PsiLambdaExpression)expression, parameterType, !isProperType(parameterType), substitutor);
       }
     }
index e68c854392c9e412074c5f57d686d3d482341e7c..14cb32ab6f1c201af5584123fa964fca8527083f 100644 (file)
@@ -16,7 +16,6 @@
 package com.intellij.psi.impl.source.resolve.graphInference.constraints;
 
 import com.intellij.codeInsight.ExceptionUtil;
-import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.psi.*;
 import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
 import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
@@ -32,13 +31,11 @@ import java.util.List;
 import java.util.Set;
 
 public class CheckedExceptionCompatibilityConstraint extends InputOutputConstraintFormula {
-  private static final Logger LOG = Logger.getInstance(CheckedExceptionCompatibilityConstraint.class);
   private final PsiExpression myExpression;
-  private PsiType myT;
 
   public CheckedExceptionCompatibilityConstraint(PsiExpression expression, PsiType t) {
+    super(t);
     myExpression = expression;
-    myT = t;
   }
 
   @Override
@@ -46,6 +43,7 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai
     if (!PsiPolyExpressionUtil.isPolyExpression(myExpression)) {
       return true;
     }
+    PsiType myT = getCurrentType();
     if (myExpression instanceof PsiParenthesizedExpression) {
       constraints.add(new CheckedExceptionCompatibilityConstraint(((PsiParenthesizedExpression)myExpression).getExpression(), myT));
       return true;
@@ -110,9 +108,7 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai
       final PsiElement body = myExpression instanceof PsiLambdaExpression ? ((PsiLambdaExpression)myExpression).getBody() : myExpression;
       if (body != null) {
         final List<PsiClassType> exceptions =  ExceptionUtil.getUnhandledExceptions(new PsiElement[] {body});
-        if (exceptions != null) {
-          thrownTypes.addAll(ContainerUtil.filter(exceptions, type -> !ExceptionUtil.isUncheckedException(type)));
-        }
+        thrownTypes.addAll(ContainerUtil.filter(exceptions, type -> !ExceptionUtil.isUncheckedException(type)));
       }
 
       if (expectedNonProperThrownTypes.isEmpty()) {
@@ -161,16 +157,6 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai
   }
 
   @Override
-  protected PsiType getT() {
-    return myT;
-  }
-
-  @Override
-  protected void setT(PsiType t) {
-    myT = t;
-  }
-
-  @Override
   protected InputOutputConstraintFormula createSelfConstraint(PsiType type, PsiExpression expression) {
     return new CheckedExceptionCompatibilityConstraint(expression, type);
   }
index 90168f99852bff7555bcd2f44d2b1fb24c276ac5..579f126f67ec89e583b6c9d36fb48cc12ef3f570 100644 (file)
@@ -18,15 +18,15 @@ import java.util.Set;
 
 public class ExpressionCompatibilityConstraint extends InputOutputConstraintFormula {
   private final PsiExpression myExpression;
-  private PsiType myT;
 
   public ExpressionCompatibilityConstraint(@NotNull PsiExpression expression, @NotNull PsiType type) {
+    super(type);
     myExpression = expression;
-    myT = type;
   }
 
   @Override
   public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) {
+    PsiType myT = getCurrentType();
     if (!PsiPolyExpressionUtil.isPolyExpression(myExpression)) {
 
       PsiType exprType = myExpression.getType();
@@ -228,16 +228,6 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
   }
 
   @Override
-  public PsiType getT() {
-    return myT;
-  }
-
-  @Override
-  protected void setT(PsiType t) {
-    myT = t;
-  }
-
-  @Override
   protected InputOutputConstraintFormula createSelfConstraint(PsiType type, PsiExpression expression) {
     return new ExpressionCompatibilityConstraint(expression, type);
   }
index 226f8b5ff672cb45e7aa1a22c37b15a8472a91b4..84b01ad5f8c0c10f3e72e9c60462f0be07a05ec5 100644 (file)
@@ -28,10 +28,13 @@ import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 public abstract class InputOutputConstraintFormula implements ConstraintFormula {
+  private PsiType myT;
+
+  protected InputOutputConstraintFormula(PsiType t) {
+    myT = t;
+  }
 
   public abstract PsiExpression getExpression();
-  protected abstract PsiType getT();
-  protected abstract void setT(PsiType t);
   protected abstract InputOutputConstraintFormula createSelfConstraint(PsiType type, PsiExpression expression);
   protected abstract void collectReturnTypeVariables(InferenceSession session,
                                                      PsiExpression psiExpression,
@@ -40,7 +43,7 @@ public abstract class InputOutputConstraintFormula implements ConstraintFormula
 
   public Set<InferenceVariable> getInputVariables(InferenceSession session) {
     final PsiExpression psiExpression = getExpression();
-    final PsiType type = getT();
+    final PsiType type = myT;
     if (psiExpression instanceof PsiFunctionalExpression) {
       final InferenceVariable inferenceVariable = session.getInferenceVariable(type);
       if (inferenceVariable != null) {
@@ -111,7 +114,7 @@ public abstract class InputOutputConstraintFormula implements ConstraintFormula
   @Nullable
   public Set<InferenceVariable> getOutputVariables(Set<InferenceVariable> inputVariables, InferenceSession session) {
     final HashSet<InferenceVariable> mentionedVariables = new HashSet<>();
-    session.collectDependencies(getT(), mentionedVariables);
+    session.collectDependencies(myT, mentionedVariables);
     if (inputVariables != null) {
       mentionedVariables.removeAll(inputVariables);
     }
@@ -120,14 +123,15 @@ public abstract class InputOutputConstraintFormula implements ConstraintFormula
 
   @Override
   public void apply(PsiSubstitutor substitutor, boolean cache) {
-    setT(substitutor.substitute(getT()));
-    if (cache) {
-      LambdaUtil.getFunctionalTypeMap().put(getExpression(), getT());
-    }
+    myT = substitutor.substitute(myT);
+  }
+
+  public PsiType getCurrentType() {
+    return myT;
   }
 
   @Override
   public String toString() {
-    return getExpression().getText() + " -> " + getT().getPresentableText();
+    return getExpression().getText() + " -> " + myT.getPresentableText();
   }
 }
index d0955f4d50badab52a02dbeff57420c212f1c3cf..80d438c498440e1a065e3437d20d9d1f2bd52206 100644 (file)
@@ -161,7 +161,7 @@ public class PsiMethodCallExpressionImpl extends ExpressionPsiElement implements
                                                       MethodCandidateInfo.isOverloadCheck(parentArgList) &&
                                                       Arrays.stream(parentArgList.getExpressions())
                                                         .map(expression -> PsiUtil.skipParenthesizedExprDown(expression))
-                                                        .noneMatch(expression -> LambdaUtil.getFunctionalTypeMap().containsKey(expression));
+                                                        .noneMatch(expression -> expression != null && ThreadLocalTypes.hasBindingFor(expression));
 
       PsiType theOnly = null;
       for (int i = 0; i < results.length; i++) {
index 3609928401e6a1fb57d8ded7daf66c6b4568d18e..2617a0509b2c433b272e5c7cd25f0d68393c8f0e 100644 (file)
@@ -1,6 +1,6 @@
 class IntStream {
   private void foo(IntStream s) {
-    s.<error descr="Ambiguous method call: both 'IntStream.map(IntUnaryOperator)' and 'IntStream.map(ObjIntFunction<Object>)' match">map</error>(i -> 1 << i);
+    s.<error descr="Ambiguous method call: both 'IntStream.map(IntUnaryOperator)' and 'IntStream.map(ObjIntFunction<Object>)' match">map</error>(i -> <error descr="Operator '<<' cannot be applied to 'int', '<lambda parameter>'">1 << i</error>);
     s.<error descr="Ambiguous method call: both 'IntStream.map(IntUnaryOperator)' and 'IntStream.map(ObjIntFunction<Object>)' match">map</error>(i -> 1);
     s.<error descr="Ambiguous method call: both 'IntStream.map(IntUnaryOperator)' and 'IntStream.map(ObjIntFunction<Object>)' match">map</error>(i -> i);
   }
index 23dc3b0237d2dbc19bc4084b5f481f19865b3080..fda3e3d6d2b44cf609ebe751f9abb31a8e62d679 100644 (file)
@@ -14,7 +14,7 @@ class Test {
   }
 
   void fooBar(IntStream1 instr){
-    Supplier<Stream<Integer>> si = () -> instr.<error descr="Ambiguous method call: both 'IntStream1.map(IntFunction<Integer>)' and 'IntStream1.map(IntUnaryOperator)' match">map</error> ((i) -> (( <error descr="Operator '%' cannot be applied to '<lambda parameter>', 'int'">i % 2</error>) == 0) ? i : -i).boxed();
+    Supplier<Stream<Integer>> si = () -> instr.<error descr="Ambiguous method call: both 'IntStream1.map(IntFunction<Integer>)' and 'IntStream1.map(IntUnaryOperator)' match">map</error> ((i) -> (( <error descr="Operator '%' cannot be applied to '<lambda parameter>', 'int'">i % 2</error>) == 0) ? i : <error descr="Operator '-' cannot be applied to '<lambda parameter>'">-i</error>).boxed();
     System.out.println(si);
     Supplier<Stream<Integer>> si1 = () -> instr.map <error descr="Ambiguous method call: both 'IntStream1.map(IntFunction<Integer>)' and 'IntStream1.map(IntUnaryOperator)' match">(null)</error>.boxed();
     System.out.println(si1);
index eab32249a3bf6b0d9526733657fd27cec9a40f04..71b16be170da2da65e63d54fe664397494374e8d 100644 (file)
@@ -14,10 +14,10 @@ abstract class Test {
     foo(x -> {
       return x += 1;
     });
-    <error descr="Ambiguous method call: both 'Test.foo(A)' and 'Test.foo(B)' match">foo</error>(x -> x += 1);
+    <error descr="Ambiguous method call: both 'Test.foo(A)' and 'Test.foo(B)' match">foo</error>(x -> <error descr="Incompatible types. Found: 'int', required: '<lambda parameter>'">x += 1</error>);
     foo(x -> 1);
     foo(x -> <error descr="Operator '!' cannot be applied to 'int'">!x</error>);
-    <error descr="Ambiguous method call: both 'Test.foo(A)' and 'Test.foo(B)' match">foo</error>(x -> ++x);
+    <error descr="Ambiguous method call: both 'Test.foo(A)' and 'Test.foo(B)' match">foo</error>(x -> <error descr="Operator '++' cannot be applied to '<lambda parameter>'">++x</error>);
     foo(x -> o instanceof String ? 1 : 0);
   }
 }