mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
java: prohibit caching when using thread-local types imposed on expressions and declarations in complex nested inference scenarios
GitOrigin-RevId: a767826dedb5d1879009ee5804e1c675d1b863ac
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a086de2ef0
commit
000ccd1dbc
@@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+22
-19
@@ -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());
|
||||
}
|
||||
return ThreadLocalTypes.performWithTypes(types -> {
|
||||
myTempTypes = types;
|
||||
try {
|
||||
doInfer(parameters, args, parent, currentMethod, initialSubstitutor);
|
||||
return prepareSubstitution();
|
||||
}
|
||||
|
||||
if (currentMethod != null) {
|
||||
if (myErrorMessages != null) {
|
||||
currentMethod.setApplicabilityError(StringUtil.join(myErrorMessages, "\n"));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-17
@@ -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()) {
|
||||
@@ -160,16 +156,6 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai
|
||||
return myExpression;
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
+2
-12
@@ -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();
|
||||
@@ -227,16 +227,6 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
|
||||
return myExpression;
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
+13
-9
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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++) {
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user