mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
graph inference: recursive calls (IDEA-119834)
This commit is contained in:
+1
-1
@@ -72,7 +72,7 @@ public class FunctionalInterfaceParameterizationUtil {
|
||||
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
|
||||
if (interfaceMethod == null) return null;
|
||||
|
||||
final InferenceSession session = new InferenceSession(PsiSubstitutor.EMPTY);
|
||||
final InferenceSession session = new InferenceSession(PsiSubstitutor.EMPTY, expr);
|
||||
PsiTypeParameter[] typeParameters = psiClass.getTypeParameters();
|
||||
if (typeParameters.length != parameters.length) {
|
||||
return null;
|
||||
|
||||
+24
-5
@@ -29,10 +29,12 @@ import com.intellij.psi.scope.MethodProcessorSetupFailedException;
|
||||
import com.intellij.psi.scope.processor.MethodCandidatesProcessor;
|
||||
import com.intellij.psi.scope.util.PsiScopesUtil;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiTypesUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.ArrayUtilRt;
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -55,17 +57,22 @@ public class InferenceSession {
|
||||
|
||||
private final InferenceIncorporationPhase myIncorporationPhase = new InferenceIncorporationPhase(this);
|
||||
|
||||
public InferenceSession(PsiSubstitutor siteSubstitutor) {
|
||||
private final PsiElement myContext;
|
||||
|
||||
public InferenceSession(PsiSubstitutor siteSubstitutor, PsiElement expr) {
|
||||
mySiteSubstitutor = siteSubstitutor;
|
||||
myContext = expr;
|
||||
}
|
||||
|
||||
public InferenceSession(PsiTypeParameter[] typeParams,
|
||||
PsiType[] leftTypes,
|
||||
PsiType[] rightTypes,
|
||||
PsiSubstitutor siteSubstitutor,
|
||||
PsiManager manager) {
|
||||
PsiManager manager,
|
||||
PsiElement context) {
|
||||
myManager = manager;
|
||||
mySiteSubstitutor = siteSubstitutor;
|
||||
myContext = context;
|
||||
|
||||
initBounds(typeParams);
|
||||
|
||||
@@ -80,9 +87,11 @@ public class InferenceSession {
|
||||
|
||||
public InferenceSession(PsiTypeParameter[] typeParams,
|
||||
PsiSubstitutor siteSubstitutor,
|
||||
PsiManager manager) {
|
||||
PsiManager manager,
|
||||
PsiElement context) {
|
||||
myManager = manager;
|
||||
mySiteSubstitutor = siteSubstitutor;
|
||||
myContext = context;
|
||||
|
||||
initBounds(typeParams);
|
||||
}
|
||||
@@ -252,6 +261,17 @@ public class InferenceSession {
|
||||
return mySiteSubstitutor;
|
||||
}
|
||||
|
||||
private boolean isInsideRecursiveCall(PsiTypeParameter parameter) {
|
||||
final PsiTypeParameterListOwner parameterOwner = parameter.getOwner();
|
||||
if (myContext != null && PsiTreeUtil.isAncestor(parameterOwner, myContext, true)) {
|
||||
final PsiModifierListOwner staticContainer = PsiUtil.getEnclosingStaticElement(myContext, null);
|
||||
if (staticContainer == null || PsiTreeUtil.isAncestor(staticContainer, parameterOwner, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void initBounds(PsiTypeParameter... typeParameters) {
|
||||
for (PsiTypeParameter parameter : typeParameters) {
|
||||
if (myInferenceVariables.containsKey(parameter)) continue;
|
||||
@@ -274,7 +294,6 @@ public class InferenceSession {
|
||||
}
|
||||
|
||||
public void addCapturedVariable(PsiTypeParameter param) {
|
||||
if (myInferenceVariables.containsKey(param)) return; //same method call
|
||||
initBounds(param);
|
||||
}
|
||||
|
||||
@@ -549,7 +568,7 @@ public class InferenceSession {
|
||||
inferred = boundCandidatesNumber > typeParameter.getExtendsListTypes().length && (typeParameter.getExtendsListTypes().length > 0 || boundCandidatesNumber > 1);
|
||||
}
|
||||
}
|
||||
if (glb != null && (acceptInitialUpperBound || inferred)) {
|
||||
if (glb != null && (acceptInitialUpperBound && !isInsideRecursiveCall(typeParameter) || inferred)) {
|
||||
inferenceVariable.setInstantiation(glb);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -38,7 +38,7 @@ public class PsiGraphInferenceHelper implements PsiInferenceHelper {
|
||||
@NotNull PsiSubstitutor partialSubstitutor,
|
||||
@Nullable PsiElement parent,
|
||||
@NotNull ParameterTypeInferencePolicy policy) {
|
||||
final InferenceSession inferenceSession = new InferenceSession(new PsiTypeParameter[]{typeParameter}, partialSubstitutor, myManager);
|
||||
final InferenceSession inferenceSession = new InferenceSession(new PsiTypeParameter[]{typeParameter}, partialSubstitutor, myManager, parent);
|
||||
inferenceSession.initExpressionConstraints(parameters, arguments, parent, null);
|
||||
return inferenceSession.infer(parameters, arguments, parent, policy).substitute(typeParameter);
|
||||
}
|
||||
@@ -53,7 +53,7 @@ public class PsiGraphInferenceHelper implements PsiInferenceHelper {
|
||||
@NotNull ParameterTypeInferencePolicy policy,
|
||||
@NotNull LanguageLevel languageLevel) {
|
||||
if (typeParameters.length == 0) return partialSubstitutor;
|
||||
final InferenceSession inferenceSession = new InferenceSession(typeParameters, partialSubstitutor, myManager);
|
||||
final InferenceSession inferenceSession = new InferenceSession(typeParameters, partialSubstitutor, myManager, parent);
|
||||
inferenceSession.initExpressionConstraints(parameters, arguments, parent, null);
|
||||
return inferenceSession.infer(parameters, arguments, parent, policy);
|
||||
}
|
||||
@@ -65,7 +65,7 @@ public class PsiGraphInferenceHelper implements PsiInferenceHelper {
|
||||
@NotNull PsiType[] rightTypes,
|
||||
@NotNull LanguageLevel languageLevel) {
|
||||
if (typeParameters.length == 0) return PsiSubstitutor.EMPTY;
|
||||
InferenceSession session = new InferenceSession(typeParameters, leftTypes, rightTypes, PsiSubstitutor.EMPTY, myManager);
|
||||
InferenceSession session = new InferenceSession(typeParameters, leftTypes, rightTypes, PsiSubstitutor.EMPTY, myManager, null);
|
||||
for (PsiType leftType : leftTypes) {
|
||||
if (!session.isProperType(leftType)) {
|
||||
return session.infer();
|
||||
@@ -104,7 +104,7 @@ public class PsiGraphInferenceHelper implements PsiInferenceHelper {
|
||||
leftTypes = new PsiType[] {arg};
|
||||
rightTypes = new PsiType[]{param};
|
||||
}
|
||||
final InferenceSession inferenceSession = new InferenceSession(new PsiTypeParameter[]{typeParam}, leftTypes, rightTypes, PsiSubstitutor.EMPTY, myManager);
|
||||
final InferenceSession inferenceSession = new InferenceSession(new PsiTypeParameter[]{typeParam}, leftTypes, rightTypes, PsiSubstitutor.EMPTY, myManager, null);
|
||||
if (inferenceSession.isProperType(param) && inferenceSession.isProperType(arg)) {
|
||||
boolean proceed = false;
|
||||
for (PsiClassType classType : typeParam.getExtendsListTypes()) {
|
||||
|
||||
+1
-1
@@ -108,7 +108,7 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
|
||||
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
|
||||
if (pair == null) {
|
||||
if (method != null) {
|
||||
InferenceSession callSession = new InferenceSession(typeParams, ((MethodCandidateInfo)resolveResult).getSiteSubstitutor(), myExpression.getManager());
|
||||
InferenceSession callSession = new InferenceSession(typeParams, ((MethodCandidateInfo)resolveResult).getSiteSubstitutor(), myExpression.getManager(), myExpression);
|
||||
final PsiExpression[] args = argumentList.getExpressions();
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
callSession.initExpressionConstraints(parameters, args, myExpression, method);
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ class Test1 {
|
||||
|
||||
class Test2 {
|
||||
protected <T, U> U exerciseOps(TestData<T> data, TerminalOp<T, U> terminal, IntermediateOp... ops) {
|
||||
<error descr="Incompatible types. Found: 'java.lang.Object', required: 'U'">return exerciseOps(data, (u, v) -> u.equals(v), terminal);</error>
|
||||
return exerciseOps(data, (u, v) -> u.equals(v), terminal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
public class Bug
|
||||
{
|
||||
|
||||
interface I<K>{}
|
||||
public static <CRN>I<CRN> create(final I<CRN> it)
|
||||
{
|
||||
final I<CRN> f = null;
|
||||
|
||||
Bug.<String>create(fn<error descr="'fn(Bug.I<java.lang.String>)' in 'Bug' cannot be applied to '(Bug.I<CRN>)'">(f)</error>);
|
||||
|
||||
return create(fn(f));
|
||||
|
||||
}
|
||||
|
||||
private static <FN>I<FN> fn(final I<FN> f)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+4
@@ -95,6 +95,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testRecursiveCalls() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user