summaryrefslogtreecommitdiff
path: root/java/java-psi-impl/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'java/java-psi-impl/src/com')
-rw-r--r--java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java15
-rw-r--r--java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java4
-rw-r--r--java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java18
-rw-r--r--java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java4
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java2
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowFactory.java29
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java6
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java3
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/light/LightTypeParameter.java4
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java5
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java42
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java314
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java9
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiGraphInferenceHelper.java9
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java65
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java4
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java22
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java13
18 files changed, 278 insertions, 290 deletions
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java b/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java
index 05b516e47ee5..966504719826 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java
@@ -49,21 +49,20 @@ import java.util.concurrent.ConcurrentMap;
public abstract class BaseExternalAnnotationsManager extends ExternalAnnotationsManager {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.BaseExternalAnnotationsManager");
+ @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
@NotNull private static final List<PsiFile> NULL_LIST = new ArrayList<PsiFile>(0);
@NotNull
private final ConcurrentMap<VirtualFile, List<PsiFile>> myExternalAnnotations = new ConcurrentSoftValueHashMap<VirtualFile, List<PsiFile>>(10, 0.75f, 2);
protected final PsiManager myPsiManager;
- @SuppressWarnings("UnusedDeclaration")
- private final LowMemoryWatcher myLowMemoryWatcher = LowMemoryWatcher.register(new Runnable() {
- @Override
- public void run() {
- dropCache();
- }
- });
-
public BaseExternalAnnotationsManager(final PsiManager psiManager) {
myPsiManager = psiManager;
+ LowMemoryWatcher.register(new Runnable() {
+ @Override
+ public void run() {
+ dropCache();
+ }
+ }, psiManager.getProject());
}
@Nullable
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java
index e2de5a55e0b3..f4154bc4fe1a 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java
@@ -843,8 +843,8 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
FoldingGroup group = FoldingGroup.newGroup("lambda");
final String prettySpace = oneLine ? " " : "";
foldElements.add(new NamedFoldingDescriptor(expression, closureStart, rangeStart, group, lambdas + prettySpace));
- if (rbrace != null && rangeEnd + 1 < closureEnd) {
- foldElements.add(new NamedFoldingDescriptor(rbrace, rangeEnd, closureEnd, group, prettySpace + "}"));
+ if (classRBrace != null && rangeEnd + 1 < closureEnd) {
+ foldElements.add(new NamedFoldingDescriptor(classRBrace, rangeEnd, closureEnd, group, prettySpace + "}"));
}
addCodeBlockFolds(body, foldElements, processedComments, document, quick);
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java
index f2b9583c49b0..1f642b18d1b1 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java
@@ -45,6 +45,7 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.xml.util.XmlStringUtil;
import org.jdom.Document;
import org.jdom.Element;
@@ -720,14 +721,21 @@ public class JavaDocInfoGenerator {
boolean generateLink, boolean splitAnnotations) {
PsiManager manager = owner.getManager();
+ Set<String> shownAnnotations = ContainerUtil.newHashSet();
+
for (PsiAnnotation annotation : annotations) {
final PsiJavaCodeReferenceElement nameReferenceElement = annotation.getNameReferenceElement();
if (nameReferenceElement == null) continue;
final PsiElement resolved = nameReferenceElement.resolve();
boolean inferred = AnnotationUtil.isInferredAnnotation(annotation);
+
+ if (!(shownAnnotations.add(annotation.getQualifiedName()) || isRepeatableAnnotationType(resolved))) {
+ continue;
+ }
+
if (resolved instanceof PsiClass) {
final PsiClass annotationType = (PsiClass)resolved;
- if (AnnotationUtil.isAnnotated(annotationType, "java.lang.annotation.Documented", false)) {
+ if (isDocumentedAnnotationType(annotationType)) {
if (inferred) buffer.append("<i>");
final PsiClassType type = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createType(annotationType, PsiSubstitutor.EMPTY);
buffer.append("@");
@@ -770,6 +778,14 @@ public class JavaDocInfoGenerator {
}
}
+ public static boolean isDocumentedAnnotationType(@Nullable PsiElement annotationType) {
+ return annotationType instanceof PsiClass && AnnotationUtil.isAnnotated((PsiClass)annotationType, "java.lang.annotation.Documented", false);
+ }
+
+ public static boolean isRepeatableAnnotationType(@Nullable PsiElement annotationType) {
+ return annotationType instanceof PsiClass && AnnotationUtil.isAnnotated((PsiClass)annotationType, CommonClassNames.JAVA_LANG_ANNOTATION_REPEATABLE, false, true);
+ }
+
private void generateMethodParameterJavaDoc(@NonNls StringBuilder buffer, PsiParameter parameter, boolean generatePrologueAndEpilogue) {
if (generatePrologueAndEpilogue)
generatePrologue(buffer);
diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java
index e18b1b5b5dab..c6c8e71fbca1 100644
--- a/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java
+++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -66,7 +66,7 @@ public class ReferenceParser {
final TypeInfo typeInfo = parseTypeInfo(builder, flags, false);
if (typeInfo != null) {
- assert notSet(flags, DISJUNCTIONS|CONJUNCTIONS) : "don't not set both flags simultaneously";
+ assert notSet(flags, DISJUNCTIONS|CONJUNCTIONS) : "don't set both flags simultaneously";
final IElementType operator = isSet(flags, DISJUNCTIONS) ? JavaTokenType.OR : isSet(flags, CONJUNCTIONS) ? JavaTokenType.AND : null;
if (operator != null && builder.getTokenType() == operator) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java
index da32b64ea092..b8f810611201 100644
--- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java
+++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java
@@ -204,7 +204,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
ProgressIndicatorProvider.checkCanceled();
ControlFlowSubRange subRange = entry.getValue();
PsiElement element = entry.getKey();
- myControlFlowFactory.registerSubRange(element, subRange, myEvaluateConstantIfCondition, myPolicy);
+ myControlFlowFactory.registerSubRange(element, subRange, myEvaluateConstantIfCondition, myEnabledShortCircuit, myPolicy);
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowFactory.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowFactory.java
index 2ba1906c422c..3159193bce4f 100644
--- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowFactory.java
+++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowFactory.java
@@ -62,19 +62,29 @@ public class ControlFlowFactory {
cachedFlows.clear();
}
+ @Deprecated
public void registerSubRange(final PsiElement codeFragment, final ControlFlowSubRange flow, final boolean evaluateConstantIfConfition,
final ControlFlowPolicy policy) {
- registerControlFlow(codeFragment, flow, evaluateConstantIfConfition, policy);
+ registerSubRange(codeFragment, flow, evaluateConstantIfConfition, true, policy);
+ }
+
+ public void registerSubRange(final PsiElement codeFragment,
+ final ControlFlowSubRange flow,
+ final boolean evaluateConstantIfConfition,
+ boolean enableShortCircuit, final ControlFlowPolicy policy) {
+ registerControlFlow(codeFragment, flow, evaluateConstantIfConfition, enableShortCircuit, policy);
}
private static class ControlFlowContext {
private final ControlFlowPolicy policy;
private final boolean evaluateConstantIfCondition;
+ private final boolean enableShortCircuit;
private final long modificationCount;
private final ControlFlow controlFlow;
- private ControlFlowContext(boolean evaluateConstantIfCondition, @NotNull ControlFlowPolicy policy, long modificationCount, @NotNull ControlFlow controlFlow) {
+ private ControlFlowContext(boolean evaluateConstantIfCondition, boolean enableShortCircuit, @NotNull ControlFlowPolicy policy, long modificationCount, @NotNull ControlFlow controlFlow) {
this.evaluateConstantIfCondition = evaluateConstantIfCondition;
+ this.enableShortCircuit = enableShortCircuit;
this.policy = policy;
this.modificationCount = modificationCount;
this.controlFlow = controlFlow;
@@ -96,9 +106,10 @@ public class ControlFlowFactory {
return result;
}
- public boolean isFor(@NotNull ControlFlowPolicy policy, final boolean evaluateConstantIfCondition, long modificationCount) {
+ public boolean isFor(@NotNull ControlFlowPolicy policy, final boolean evaluateConstantIfCondition, final boolean enableShortCircuit, long modificationCount) {
if (modificationCount != this.modificationCount) return false;
if (!policy.equals(this.policy)) return false;
+ if (enableShortCircuit != this.enableShortCircuit) return false;
// optimization: when no constant condition were computed, both control flows are the same
if (!controlFlow.isConstantConditionOccurred()) return true;
@@ -107,7 +118,7 @@ public class ControlFlowFactory {
}
private boolean isFor(@NotNull ControlFlowContext that) {
- return isFor(that.policy, that.evaluateConstantIfCondition, that.modificationCount);
+ return isFor(that.policy, that.evaluateConstantIfCondition, that.enableShortCircuit, that.modificationCount);
}
}
@@ -129,28 +140,30 @@ public class ControlFlowFactory {
final long modificationCount = element.getManager().getModificationTracker().getModificationCount();
ConcurrentList<ControlFlowContext> cached = getOrCreateCachedFlowsForElement(element);
for (ControlFlowContext context : cached) {
- if (context.isFor(policy, evaluateConstantIfCondition,modificationCount)) return context.controlFlow;
+ if (context.isFor(policy, evaluateConstantIfCondition, enableShortCircuit, modificationCount)) return context.controlFlow;
}
ControlFlow controlFlow = new ControlFlowAnalyzer(element, policy, enableShortCircuit, evaluateConstantIfCondition).buildControlFlow();
- ControlFlowContext context = createContext(evaluateConstantIfCondition, policy, controlFlow, modificationCount);
+ ControlFlowContext context = createContext(evaluateConstantIfCondition, enableShortCircuit, policy, controlFlow, modificationCount);
cached.addIfAbsent(context);
return controlFlow;
}
@NotNull
private static ControlFlowContext createContext(final boolean evaluateConstantIfCondition,
+ boolean enableShortCircuit,
@NotNull ControlFlowPolicy policy,
@NotNull ControlFlow controlFlow,
final long modificationCount) {
- return new ControlFlowContext(evaluateConstantIfCondition, policy, modificationCount,controlFlow);
+ return new ControlFlowContext(evaluateConstantIfCondition, enableShortCircuit, policy, modificationCount,controlFlow);
}
private void registerControlFlow(@NotNull PsiElement element,
@NotNull ControlFlow flow,
boolean evaluateConstantIfCondition,
+ boolean enableShortCircuit,
@NotNull ControlFlowPolicy policy) {
final long modificationCount = element.getManager().getModificationTracker().getModificationCount();
- ControlFlowContext controlFlowContext = createContext(evaluateConstantIfCondition, policy, flow, modificationCount);
+ ControlFlowContext controlFlowContext = createContext(evaluateConstantIfCondition, enableShortCircuit, policy, flow, modificationCount);
ConcurrentList<ControlFlowContext> cached = getOrCreateCachedFlowsForElement(element);
cached.addIfAbsent(controlFlowContext);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java
index 7c597e495f2e..9c9525aef859 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java
@@ -80,14 +80,14 @@ public class PsiSubstitutorImpl implements PsiSubstitutor {
}
private boolean containsInMap(PsiTypeParameter typeParameter) {
- if (typeParameter instanceof LightTypeParameter) {
+ if (typeParameter instanceof LightTypeParameter && ((LightTypeParameter)typeParameter).useDelegateToSubstitute()) {
typeParameter = ((LightTypeParameter)typeParameter).getDelegate();
}
return mySubstitutionMap.containsKey(typeParameter);
}
private PsiType getFromMap(@NotNull PsiTypeParameter typeParameter) {
- if (typeParameter instanceof LightTypeParameter) {
+ if (typeParameter instanceof LightTypeParameter && ((LightTypeParameter)typeParameter).useDelegateToSubstitute()) {
typeParameter = ((LightTypeParameter)typeParameter).getDelegate();
}
return mySubstitutionMap.get(typeParameter);
@@ -394,7 +394,7 @@ public class PsiSubstitutorImpl implements PsiSubstitutor {
}
}
}
- } else if (substituted instanceof PsiWildcardType && ((PsiWildcardType)substituted).isSuper()) {
+ } else if (substituted instanceof PsiWildcardType && ((PsiWildcardType)substituted).isSuper() && !(oldSubstituted instanceof PsiCapturedWildcardType)) {
final PsiType erasure = TypeConversionUtil.erasure(((PsiWildcardType)substituted).getBound());
if (erasure != null) {
final PsiType[] boundTypes = typeParameter.getExtendsListTypes();
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java
index c188c3a38013..9129052bf74f 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java
@@ -263,7 +263,6 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya
processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, this);
ElementClassHint classHint = processor.getHint(ElementClassHint.KEY);
- final JavaPsiFacade facade = getFacade();
final Condition<String> nameCondition = processor.getHint(JavaCompletionHints.NAME_FILTER);
if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.CLASS)) {
@@ -291,7 +290,7 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya
for (PsiPackage pack : packs) {
final String packageName = pack.getName();
if (packageName == null) continue;
- if (!facade.getNameHelper().isIdentifier(packageName, PsiUtil.getLanguageLevel(this))) {
+ if (!PsiNameHelper.getInstance(myManager.getProject()).isIdentifier(packageName, PsiUtil.getLanguageLevel(this))) {
continue;
}
if (!processor.execute(pack, state)) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/light/LightTypeParameter.java b/java/java-psi-impl/src/com/intellij/psi/impl/light/LightTypeParameter.java
index 6775a64c59ef..3cd347648a07 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/light/LightTypeParameter.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/light/LightTypeParameter.java
@@ -79,6 +79,10 @@ public class LightTypeParameter extends LightClass implements PsiTypeParameter {
return getDelegate().addAnnotation(qualifiedName);
}
+ public boolean useDelegateToSubstitute() {
+ return true;
+ }
+
@Override
public String toString() {
return "PsiTypeParameter:" + getName();
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java
index b4b188c772cc..9742e0f28608 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java
@@ -36,7 +36,7 @@ public class FunctionalInterfaceParameterizationUtil {
}
if (classType instanceof PsiClassType) {
for (PsiType type : ((PsiClassType)classType).getParameters()) {
- if (type instanceof PsiWildcardType || type instanceof PsiCapturedWildcardType) {
+ if (type instanceof PsiWildcardType) {
return true;
}
}
@@ -94,7 +94,8 @@ public class FunctionalInterfaceParameterizationUtil {
final InferenceSession session = new InferenceSession(typeParameters, PsiSubstitutor.EMPTY, expr.getManager(), expr);
for (int i = 0; i < targetMethodParams.length; i++) {
- session.addConstraint(new TypeEqualityConstraint(lambdaParams[i].getType(), targetMethodParams[i].getType()));
+ session.addConstraint(new TypeEqualityConstraint(lambdaParams[i].getType(),
+ session.substituteWithInferenceVariables(targetMethodParams[i].getType())));
}
if (!session.repeatInferencePhases(false)) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java
index 9766122e31d0..9c8b8b4772b3 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java
@@ -89,28 +89,6 @@ public class InferenceIncorporationPhase {
upDown(lowerBounds, eqBounds, substitutor);
upUp(upperBounds);
-
- for (PsiType eqBound : eqBounds) {
- if (mySession.isProperType(eqBound)) {
- for (PsiType upperBound : upperBounds) {
- if (!mySession.isProperType(upperBound)) {
- addConstraint(new StrictSubtypingConstraint(substitutor.substitute(upperBound), eqBound));
- }
- }
-
- for (PsiType lowerBound : lowerBounds) {
- if (!mySession.isProperType(lowerBound)) {
- addConstraint(new StrictSubtypingConstraint(eqBound, substitutor.substitute(lowerBound)));
- }
- }
-
- for (PsiType otherEqBound : eqBounds) {
- if (eqBound != otherEqBound && !mySession.isProperType(otherEqBound)) {
- addConstraint(new TypeEqualityConstraint(substitutor.substitute(otherEqBound), eqBound));
- }
- }
- }
- }
}
for (Pair<PsiTypeParameter[], PsiClassType> capture : myCaptures) {
@@ -135,7 +113,7 @@ public class InferenceIncorporationPhase {
if (aType instanceof PsiWildcardType) {
for (PsiType eqBound : eqBounds) {
- if (mySession.isProperType(eqBound)) return false;
+ if (mySession.getInferenceVariable(eqBound) == null) return false;
}
final PsiClassType[] paramBounds = parameters[i].getExtendsListTypes();
@@ -143,15 +121,15 @@ public class InferenceIncorporationPhase {
if (!((PsiWildcardType)aType).isBounded()) {
for (PsiType upperBound : upperBounds) {
- if (mySession.isProperType(upperBound)) {
+ if (mySession.getInferenceVariable(upperBound) == null) {
for (PsiClassType paramBound : paramBounds) {
- addConstraint(new StrictSubtypingConstraint(upperBound, paramBound));
+ addConstraint(new StrictSubtypingConstraint(upperBound, mySession.substituteWithInferenceVariables(paramBound)));
}
}
}
for (PsiType lowerBound : lowerBounds) {
- if (mySession.isProperType(lowerBound)) return false;
+ if (mySession.getInferenceVariable(lowerBound) == null) return false;
}
} else if (((PsiWildcardType)aType).isExtends()) {
@@ -159,19 +137,19 @@ public class InferenceIncorporationPhase {
final PsiType extendsBound = ((PsiWildcardType)aType).getExtendsBound();
for (PsiType upperBound : upperBounds) {
- if (mySession.isProperType(upperBound)) {
+ if (mySession.getInferenceVariable(upperBound) == null) {
if (paramBounds.length == 1 && paramBounds[0].equalsToText(CommonClassNames.JAVA_LANG_OBJECT) || paramBounds.length == 0) {
addConstraint(new StrictSubtypingConstraint(upperBound, extendsBound));
} else if (extendsBound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
for (PsiClassType paramBound : paramBounds) {
- addConstraint(new StrictSubtypingConstraint(upperBound, paramBound));
+ addConstraint(new StrictSubtypingConstraint(upperBound, mySession.substituteWithInferenceVariables(paramBound)));
}
}
}
}
for (PsiType lowerBound : lowerBounds) {
- if (mySession.isProperType(lowerBound)) return false;
+ if (mySession.getInferenceVariable(lowerBound) == null) return false;
}
} else {
@@ -179,15 +157,15 @@ public class InferenceIncorporationPhase {
final PsiType superBound = ((PsiWildcardType)aType).getSuperBound();
for (PsiType upperBound : upperBounds) {
- if (mySession.isProperType(upperBound)) {
+ if (mySession.getInferenceVariable(upperBound) == null) {
for (PsiClassType paramBound : paramBounds) {
- addConstraint(new StrictSubtypingConstraint(paramBound, upperBound));
+ addConstraint(new StrictSubtypingConstraint(mySession.substituteWithInferenceVariables(paramBound), upperBound));
}
}
}
for (PsiType lowerBound : lowerBounds) {
- if (mySession.isProperType(lowerBound)) {
+ if (mySession.getInferenceVariable(lowerBound) == null) {
addConstraint(new StrictSubtypingConstraint(lowerBound, superBound));
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
index 27e34f00a25f..35db6c29bc0c 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
@@ -15,10 +15,12 @@
*/
package com.intellij.psi.impl.source.resolve.graphInference;
+import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.resolve.graphInference.constraints.*;
@@ -42,8 +44,14 @@ public class InferenceSession {
public static final Key<PsiType> LOWER_BOUND = Key.create("LowBound");
private static final Key<Boolean> ERASED = Key.create("UNCHECKED_CONVERSION");
+ private static final Function<Pair<PsiType, PsiType>, PsiType> UPPER_BOUND_FUNCTION = new Function<Pair<PsiType, PsiType>, PsiType>() {
+ @Override
+ public PsiType fun(Pair<PsiType, PsiType> pair) {
+ return GenericsUtil.getGreatestLowerBound(pair.first, pair.second);
+ }
+ };
- private final Map<PsiTypeParameter, InferenceVariable> myInferenceVariables = new LinkedHashMap<PsiTypeParameter, InferenceVariable>();
+ private final Set<InferenceVariable> myInferenceVariables = new LinkedHashSet<InferenceVariable>();
private final List<ConstraintFormula> myConstraints = new ArrayList<ConstraintFormula>();
private final Set<ConstraintFormula> myConstraintsCopy = new HashSet<ConstraintFormula>();
@@ -56,8 +64,14 @@ public class InferenceSession {
private final InferenceIncorporationPhase myIncorporationPhase = new InferenceIncorporationPhase(this);
private final PsiElement myContext;
-
- private final PsiTypeParameter[] myParamsToInfer;
+
+ private PsiSubstitutor myInferenceSubstitution = PsiSubstitutor.EMPTY;
+ private Map<PsiElement, InferenceSession> myNestedSessions = new HashMap<PsiElement, InferenceSession>();
+ public void registerNestedSession(InferenceSession session) {
+ propagateVariables(session.getInferenceVariables());
+ myNestedSessions.put(session.getContext(), session);
+ myNestedSessions.putAll(session.myNestedSessions);
+ }
public InferenceSession(PsiTypeParameter[] typeParams,
PsiType[] leftTypes,
@@ -70,13 +84,12 @@ public class InferenceSession {
myContext = context;
initBounds(typeParams);
- myParamsToInfer = typeParams;
LOG.assertTrue(leftTypes.length == rightTypes.length);
for (int i = 0; i < leftTypes.length; i++) {
final PsiType rightType = mySiteSubstitutor.substitute(rightTypes[i]);
if (rightType != null) {
- addConstraint(new TypeCompatibilityConstraint(leftTypes[i], rightType));
+ addConstraint(new TypeCompatibilityConstraint(substituteWithInferenceVariables(leftTypes[i]), substituteWithInferenceVariables(rightType)));
}
}
}
@@ -90,11 +103,6 @@ public class InferenceSession {
myContext = context;
initBounds(typeParams);
- myParamsToInfer = typeParams;
- }
-
- public PsiTypeParameter[] getParamsToInfer() {
- return myParamsToInfer;
}
public void initExpressionConstraints(PsiParameter[] parameters, PsiExpression[] args, PsiElement parent, PsiMethod method) {
@@ -117,7 +125,7 @@ public class InferenceSession {
for (int i = 0; i < args.length; i++) {
if (args[i] != null && isPertinentToApplicability(args[i], method)) {
PsiType parameterType = getParameterType(parameters, i, mySiteSubstitutor, varargs);
- addConstraint(new ExpressionCompatibilityConstraint(args[i], parameterType));
+ addConstraint(new ExpressionCompatibilityConstraint(args[i], substituteWithInferenceVariables(parameterType)));
}
}
}
@@ -213,7 +221,7 @@ public class InferenceSession {
final MethodCandidateInfo.CurrentCandidateProperties properties = getCurrentProperties(parent);
if (!repeatInferencePhases(true)) {
//inferred result would be checked as candidate won't be applicable
- return resolveSubset(myInferenceVariables.values(), mySiteSubstitutor);
+ return resolveSubset(myInferenceVariables, mySiteSubstitutor);
}
if (properties != null && !properties.isApplicabilityCheck()) {
@@ -235,20 +243,17 @@ public class InferenceSession {
}
}
- final PsiSubstitutor substitutor = resolveBounds(myInferenceVariables.values(), mySiteSubstitutor);
+ final PsiSubstitutor substitutor = resolveBounds(myInferenceVariables, mySiteSubstitutor);
if (substitutor != null) {
if (myContext != null) {
myContext.putUserData(ERASED, myErased);
}
mySiteSubstitutor = substitutor;
- for (PsiTypeParameter parameter : substitutor.getSubstitutionMap().keySet()) {
- final InferenceVariable variable = getInferenceVariable(parameter);
- if (variable != null) {
- variable.setInstantiation(substitutor.substitute(parameter));
- }
+ for (InferenceVariable variable : myInferenceVariables) {
+ variable.setInstantiation(substitutor.substitute(variable.getParameter()));
}
} else {
- return resolveSubset(myInferenceVariables.values(), mySiteSubstitutor);
+ return resolveSubset(myInferenceVariables, mySiteSubstitutor);
}
return prepareSubstitution();
@@ -262,12 +267,16 @@ public class InferenceSession {
boolean varargs, boolean toplevel) {
for (int i = 0; i < args.length; i++) {
if (args[i] != null) {
- PsiType parameterType = getParameterType(parameters, i, siteSubstitutor, varargs);
+ InferenceSession session = myNestedSessions.get(PsiTreeUtil.getParentOfType(args[i], PsiCallExpression.class));
+ if (session == null) {
+ session = this;
+ }
+ PsiType parameterType = session.substituteWithInferenceVariables(getParameterType(parameters, i, siteSubstitutor, varargs));
if (!isPertinentToApplicability(args[i], parentMethod)) {
additionalConstraints.add(new ExpressionCompatibilityConstraint(args[i], parameterType));
}
additionalConstraints.add(new CheckedExceptionCompatibilityConstraint(args[i], parameterType));
- if (args[i] instanceof PsiCallExpression) {
+ if (args[i] instanceof PsiCallExpression && PsiPolyExpressionUtil.isPolyExpression(args[i])) {
//If the expression is a poly class instance creation expression (15.9) or a poly method invocation expression (15.12),
//the set contains all constraint formulas that would appear in the set C when determining the poly expression's invocation type.
final PsiCallExpression callExpression = (PsiCallExpression)args[i];
@@ -299,18 +308,18 @@ public class InferenceSession {
return callExpression.resolveMethodGenerics();
}
};
- final JavaResolveResult result = expression == null
+ MethodCandidateInfo.CurrentCandidateProperties properties = MethodCandidateInfo.getCurrentMethod(argumentList);
+ final JavaResolveResult result = properties != null ? null :
+ expression == null
? computableResolve.compute()
: PsiResolveHelper.ourGraphGuard.doPreventingRecursion(expression, false, computableResolve);
- if (result instanceof MethodCandidateInfo) {
- final PsiMethod method = ((MethodCandidateInfo)result).getElement();
- //need to get type parameters for 2 level nested expressions (they won't be covered by expression constraints on this level?!)
- initBounds(method.getTypeParameters());
+ final PsiMethod method = result instanceof MethodCandidateInfo ? ((MethodCandidateInfo)result).getElement() : properties != null ? properties.getMethod() : null;
+ if (method != null) {
final PsiExpression[] newArgs = argumentList.getExpressions();
final PsiParameter[] newParams = method.getParameterList().getParameters();
if (newParams.length > 0) {
- collectAdditionalConstraints(newParams, newArgs, method, ((MethodCandidateInfo)result).getSiteSubstitutor(),
- additionalConstraints, ((MethodCandidateInfo)result).isVarargs(), false);
+ collectAdditionalConstraints(newParams, newArgs, method, result != null ? ((MethodCandidateInfo)result).getSiteSubstitutor() : properties.getSubstitutor(),
+ additionalConstraints, result != null ? ((MethodCandidateInfo)result).isVarargs() : properties.isVarargs(), false);
}
}
}
@@ -321,14 +330,14 @@ public class InferenceSession {
for (InferenceVariable variable : variables) {
final PsiType equalsBound = getEqualsBound(variable, substitutor);
if (!(equalsBound instanceof PsiPrimitiveType)) {
- substitutor = substitutor.put(variable.getParameter(), equalsBound);
+ substitutor = substitutor.put(variable, equalsBound);
}
}
return substitutor;
}
private PsiSubstitutor prepareSubstitution() {
- for (InferenceVariable inferenceVariable : myInferenceVariables.values()) {
+ for (InferenceVariable inferenceVariable : myInferenceVariables) {
final PsiTypeParameter typeParameter = inferenceVariable.getParameter();
PsiType instantiation = inferenceVariable.getInstantiation();
if (instantiation == PsiType.NULL) {
@@ -340,33 +349,24 @@ 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) {
+ initBounds(myContext, typeParameters);
}
- public boolean initBounds(PsiTypeParameter... typeParameters) {
- return initBounds(myContext, typeParameters);
- }
-
- public boolean initBounds(PsiElement context, PsiTypeParameter... typeParameters) {
- boolean sameMethodCall = false;
+ public InferenceVariable[] initBounds(PsiElement context, PsiTypeParameter... typeParameters) {
+ List<InferenceVariable> result = new ArrayList<InferenceVariable>(typeParameters.length);
for (PsiTypeParameter parameter : typeParameters) {
- if (myInferenceVariables.containsKey(parameter)) {
- sameMethodCall = true;
- continue;
- }
InferenceVariable variable = new InferenceVariable(context, parameter);
+ result.add(variable);
+ myInferenceSubstitution = myInferenceSubstitution.put(parameter,
+ JavaPsiFacade.getElementFactory(variable.getProject()).createType(variable));
+ }
+ for (InferenceVariable variable : result) {
+ PsiTypeParameter parameter = variable.getParameter();
boolean added = false;
final PsiClassType[] extendsListTypes = parameter.getExtendsListTypes();
for (PsiType classType : extendsListTypes) {
- classType = mySiteSubstitutor.substitute(classType);
+ classType = substituteWithInferenceVariables(mySiteSubstitutor.substitute(classType));
if (isProperType(classType)) {
added = true;
}
@@ -376,9 +376,9 @@ public class InferenceSession {
variable.addBound(PsiType.getJavaLangObject(parameter.getManager(), parameter.getResolveScope()),
InferenceBound.UPPER);
}
- myInferenceVariables.put(parameter, variable);
}
- return sameMethodCall;
+ myInferenceVariables.addAll(result);
+ return result.toArray(new InferenceVariable[result.size()]);
}
private void initReturnTypeConstraint(PsiMethod method, final PsiCallExpression context) {
@@ -393,7 +393,7 @@ public class InferenceSession {
}
for (PsiClassType thrownType : method.getThrowsList().getReferencedTypes()) {
- final InferenceVariable variable = getInferenceVariable(thrownType);
+ final InferenceVariable variable = getInferenceVariable(substituteWithInferenceVariables(thrownType));
if (variable != null) {
variable.setThrownBound();
}
@@ -401,6 +401,7 @@ public class InferenceSession {
}
public void registerReturnTypeConstraints(PsiType returnType, PsiType targetType) {
+ returnType = substituteWithInferenceVariables(returnType);
final InferenceVariable inferenceVariable = shouldResolveAndInstantiate(returnType, targetType);
if (inferenceVariable != null) {
final PsiSubstitutor substitutor = resolveSubset(Collections.singletonList(inferenceVariable), mySiteSubstitutor);
@@ -416,17 +417,9 @@ public class InferenceSession {
if (psiClass != null) {
LOG.assertTrue(returnType instanceof PsiClassType);
final PsiTypeParameter[] typeParameters = psiClass.getTypeParameters();
- PsiSubstitutor subst = PsiSubstitutor.EMPTY;
- final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(psiClass.getProject());
- PsiTypeParameter[] copy = new PsiTypeParameter[typeParameters.length];
- for (int i = 0; i < typeParameters.length; i++) {
- PsiTypeParameter typeParameter = typeParameters[i];
- copy[i] = elementFactory.createTypeParameterFromText("rCopy" + typeParameter.getName(), null);
- initBounds(myContext, copy[i]);
- subst = subst.put(typeParameter, elementFactory.createType(copy[i]));
- }
- final PsiType substitutedCapture = PsiUtil.captureToplevelWildcards(subst.substitute(returnType), myContext);
- myIncorporationPhase.addCapture(copy, (PsiClassType)returnType);
+ InferenceVariable[] copy = initBounds(myContext, typeParameters);
+ final PsiType substitutedCapture = PsiUtil.captureToplevelWildcards(returnType, myContext);
+ myIncorporationPhase.addCapture(copy, (PsiClassType)substituteWithInferenceVariables(returnType));
addConstraint(new TypeCompatibilityConstraint(targetType, substitutedCapture));
}
} else {
@@ -584,8 +577,8 @@ public class InferenceSession {
public InferenceVariable getInferenceVariable(PsiType psiType) {
final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(psiType);
- if (psiClass instanceof PsiTypeParameter) {
- return myInferenceVariables.get(psiClass);
+ if (psiClass instanceof InferenceVariable) {
+ return (InferenceVariable)psiClass;
}
return null;
}
@@ -694,7 +687,13 @@ public class InferenceSession {
while (!allVars.isEmpty()) {
final List<InferenceVariable> vars = InferenceVariablesOrder.resolveOrder(allVars, this);
if (!myIncorporationPhase.hasCaptureConstraints(vars)) {
- final PsiSubstitutor firstSubstitutor = resolveSubset(vars, substitutor);
+ PsiSubstitutor firstSubstitutor = resolveSubset(vars, substitutor);
+ if (firstSubstitutor != null) {
+ final Set<PsiTypeParameter> parameters = firstSubstitutor.getSubstitutionMap().keySet();
+ if (GenericsUtil.findTypeParameterWithBoundError(parameters.toArray(new PsiTypeParameter[parameters.size()]), firstSubstitutor, myContext, true) != null) {
+ firstSubstitutor = null;
+ }
+ }
if (firstSubstitutor != null) {
substitutor = firstSubstitutor;
allVars.removeAll(vars);
@@ -703,73 +702,102 @@ public class InferenceSession {
}
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(getManager().getProject());
- for (InferenceVariable var : vars) {
- final PsiTypeParameter parameter = var.getParameter();
- final PsiTypeParameter copy = elementFactory.createTypeParameterFromText("z" + parameter.getName(), null);
- final PsiType lub = getLowerBound(var, substitutor);
- final PsiType glb = getUpperBound(var, substitutor);
- final InferenceVariable zVariable = new InferenceVariable(var.getCallContext(), copy);
- zVariable.addBound(glb, InferenceBound.UPPER);
+ final PsiTypeParameter[] freshParameters = createFreshVariables(vars);
+ for (int i = 0; i < freshParameters.length; i++) {
+ PsiTypeParameter parameter = freshParameters[i];
+ final InferenceVariable var = vars.get(i);
+ final PsiType lub = getLowerBound(var, PsiSubstitutor.EMPTY);
if (lub != PsiType.NULL) {
- if (!TypeConversionUtil.isAssignable(glb, lub)) {
- return null;
+ for (PsiClassType upperBoundType : parameter.getExtendsListTypes()) {
+ if (!TypeConversionUtil.isAssignable(upperBoundType, lub)) {
+ return null;
+ }
}
- copy.putUserData(LOWER_BOUND, lub);
- zVariable.addBound(lub, InferenceBound.LOWER);
+ parameter.putUserData(LOWER_BOUND, lub);
}
- myInferenceVariables.put(copy, zVariable);
- allVars.add(zVariable);
- var.addBound(elementFactory.createType(copy), InferenceBound.EQ);
+ var.addBound(elementFactory.createType(parameter), InferenceBound.EQ);
}
myIncorporationPhase.forgetCaptures(vars);
- if (!myIncorporationPhase.incorporate()) {
+ if (!repeatInferencePhases(true)) {
return null;
}
}
return substitutor;
}
- private PsiType getLowerBound(InferenceVariable var, PsiSubstitutor substitutor) {
- return composeBound(var, InferenceBound.LOWER, new Function<Pair<PsiType, PsiType>, PsiType>() {
+ private PsiTypeParameter[] createFreshVariables(final List<InferenceVariable> vars) {
+ final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(getManager().getProject());
+
+ PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
+ final PsiTypeParameter[] yVars = new PsiTypeParameter[vars.size()];
+ for (int i = 0; i < vars.size(); i++) {
+ InferenceVariable var = vars.get(i);
+ final PsiTypeParameter parameter = var.getParameter();
+ yVars[i] = elementFactory.createTypeParameterFromText(getFreshVariableName(var), parameter);
+ substitutor = substitutor.put(var, elementFactory.createType(yVars[i]));
+ }
+
+
+ final PsiSubstitutor ySubstitutor = substitutor;
+ final String classText = "class I<" + StringUtil.join(vars, new Function<InferenceVariable, String>() {
@Override
- public PsiType fun(Pair<PsiType, PsiType> pair) {
- return GenericsUtil.getLeastUpperBound(pair.first, pair.second, myManager);
- }
- }, substitutor);
+ public String fun(InferenceVariable variable) {
+ final PsiType glb = composeBound(variable, InferenceBound.UPPER, UPPER_BOUND_FUNCTION, ySubstitutor, true);
+ return getFreshVariableName(variable) + " extends " + glb.getInternalCanonicalText();
+ }
+ }, ", ") + ">{}";
+
+ final PsiFile file =
+ PsiFileFactory.getInstance(getManager().getProject()).createFileFromText("inference_dummy.java", JavaFileType.INSTANCE, classText);
+ LOG.assertTrue(file instanceof PsiJavaFile, classText);
+ final PsiClass[] classes = ((PsiJavaFile)file).getClasses();
+ LOG.assertTrue(classes.length == 1, classText);
+ return classes[0].getTypeParameters();
+ }
+
+ private static String getFreshVariableName(InferenceVariable var) {
+ return var.getName();
}
private PsiSubstitutor resolveSubset(Collection<InferenceVariable> vars, PsiSubstitutor substitutor) {
for (InferenceVariable var : vars) {
LOG.assertTrue(var.getInstantiation() == PsiType.NULL);
final PsiTypeParameter typeParameter = var.getParameter();
+ if (substitutor.getSubstitutionMap().containsKey(typeParameter) && var.getCallContext() != myContext) {
+ continue;//todo
+ }
+
final PsiType eqBound = getEqualsBound(var, substitutor);
if (eqBound != PsiType.NULL && eqBound instanceof PsiPrimitiveType) continue;
- final PsiType lub = eqBound != PsiType.NULL && (myErased || eqBound != null) ? eqBound : getLowerBound(var, substitutor);
- if (lub != PsiType.NULL) {
- substitutor = substitutor.put(typeParameter, lub);
- }
- else if (var.isThrownBound() && isThrowable(var.getBounds(InferenceBound.UPPER))) {
- final PsiClassType runtimeException = PsiType.getJavaLangRuntimeException(myManager, GlobalSearchScope.allScope(myManager.getProject()));
- substitutor = substitutor.put(typeParameter, runtimeException);
- }
- else {
- if (substitutor.getSubstitutionMap().get(typeParameter) != null) continue;
- substitutor = substitutor.put(typeParameter, myErased ? null : getUpperBound(var, substitutor));
+ PsiType type = eqBound != PsiType.NULL && (myErased || eqBound != null) ? eqBound : getLowerBound(var, substitutor);
+ if (type == PsiType.NULL) {
+ if (var.isThrownBound() && isThrowable(var.getBounds(InferenceBound.UPPER))) {
+ type = PsiType.getJavaLangRuntimeException(myManager, GlobalSearchScope.allScope(myManager.getProject()));
+ }
+ else {
+ if (substitutor.getSubstitutionMap().get(typeParameter) != null) continue;
+ type = myErased ? null : getUpperBound(var, substitutor);
+ }
}
+ substitutor = substitutor.put(typeParameter, type);
}
return substitutor;
}
- private PsiType getUpperBound(InferenceVariable var, PsiSubstitutor substitutor) {
- return composeBound(var, InferenceBound.UPPER, new Function<Pair<PsiType, PsiType>, PsiType>() {
+ private PsiType getLowerBound(InferenceVariable var, PsiSubstitutor substitutor) {
+ return composeBound(var, InferenceBound.LOWER, new Function<Pair<PsiType, PsiType>, PsiType>() {
@Override
public PsiType fun(Pair<PsiType, PsiType> pair) {
- return GenericsUtil.getGreatestLowerBound(pair.first, pair.second);
+ return GenericsUtil.getLeastUpperBound(pair.first, pair.second, myManager);
}
}, substitutor);
}
+ private PsiType getUpperBound(InferenceVariable var, PsiSubstitutor substitutor) {
+ return composeBound(var, InferenceBound.UPPER, UPPER_BOUND_FUNCTION, substitutor);
+ }
+
public PsiType getEqualsBound(InferenceVariable var, PsiSubstitutor substitutor) {
return composeBound(var, InferenceBound.EQ, new Function<Pair<PsiType, PsiType>, PsiType>() {
@Override
@@ -783,16 +811,19 @@ public class InferenceSession {
InferenceBound boundType,
Function<Pair<PsiType, PsiType>, PsiType> fun,
PsiSubstitutor substitutor) {
+ return composeBound(variable, boundType, fun, substitutor, false);
+ }
+
+ private PsiType composeBound(InferenceVariable variable,
+ InferenceBound boundType,
+ Function<Pair<PsiType, PsiType>, PsiType> fun,
+ PsiSubstitutor substitutor,
+ boolean includeNonProperBounds) {
final List<PsiType> lowerBounds = variable.getBounds(boundType);
PsiType lub = PsiType.NULL;
- List<PsiType> dTypes = new ArrayList<PsiType>();
for (PsiType lowerBound : lowerBounds) {
lowerBound = substituteNonProperBound(lowerBound, substitutor);
- final HashSet<InferenceVariable> dependencies = new HashSet<InferenceVariable>();
- collectDependencies(lowerBound, dependencies);
- if (dependencies.size() == 1 && dependencies.contains(variable) && isInsideRecursiveCall(dependencies)) {
- lub = JavaPsiFacade.getElementFactory(myManager.getProject()).createType(variable.getParameter());
- } else if (dependencies.isEmpty() || isInsideRecursiveCall(dependencies)) {
+ if (includeNonProperBounds || isProperType(lowerBound)) {
if (lub == PsiType.NULL) {
lub = lowerBound;
}
@@ -804,13 +835,6 @@ public class InferenceSession {
return lub;
}
- private boolean isInsideRecursiveCall(HashSet<InferenceVariable> dependencies) {
- for (InferenceVariable dependency : dependencies) {
- if (!isInsideRecursiveCall(dependency.getParameter())) return false;
- }
- return true;
- }
-
public PsiManager getManager() {
return myManager;
}
@@ -820,7 +844,7 @@ public class InferenceSession {
}
public Collection<InferenceVariable> getInferenceVariables() {
- return myInferenceVariables.values();
+ return myInferenceVariables;
}
public void addConstraint(ConstraintFormula constraint) {
@@ -829,10 +853,6 @@ public class InferenceSession {
}
}
- public Collection<PsiTypeParameter> getTypeParams() {
- return myInferenceVariables.keySet();
- }
-
private boolean proceedWithAdditionalConstraints(Set<ConstraintFormula> additionalConstraints) {
final PsiSubstitutor siteSubstitutor = mySiteSubstitutor;
@@ -855,7 +875,7 @@ public class InferenceSession {
}
//resolve input variables
- PsiSubstitutor substitutor = resolveSubset(varsToResolve, retrieveNonPrimitiveEqualsBounds(getInferenceVariables()).putAll(siteSubstitutor));
+ PsiSubstitutor substitutor = resolveSubset(varsToResolve, siteSubstitutor);
if (substitutor == null) {
return false;
}
@@ -972,7 +992,7 @@ public class InferenceSession {
for (int i = 0; i < functionalMethodParameters.length; i++) {
final PsiType pType = signature.getParameterTypes()[i];
- addConstraint(new TypeCompatibilityConstraint(getParameterType(parameters, i, PsiSubstitutor.EMPTY, varargs),
+ addConstraint(new TypeCompatibilityConstraint(substituteWithInferenceVariables(getParameterType(parameters, i, PsiSubstitutor.EMPTY, varargs)),
PsiImplUtil.normalizeWildcardTypeByPosition(pType, reference)));
}
}
@@ -1003,11 +1023,11 @@ public class InferenceSession {
final PsiType qType = JavaPsiFacade.getElementFactory(method.getProject()).createType(containingClass, psiSubstitutor);
- addConstraint(new TypeCompatibilityConstraint(qType, pType));
+ addConstraint(new TypeCompatibilityConstraint(substituteWithInferenceVariables(qType), pType));
for (int i = 0; i < signature.getParameterTypes().length - 1; i++) {
final PsiType interfaceParamType = signature.getParameterTypes()[i + 1];
- addConstraint(new TypeCompatibilityConstraint(getParameterType(parameters, i, PsiSubstitutor.EMPTY, varargs),
+ addConstraint(new TypeCompatibilityConstraint(substituteWithInferenceVariables(getParameterType(parameters, i, PsiSubstitutor.EMPTY, varargs)),
PsiImplUtil.normalizeWildcardTypeByPosition(interfaceParamType, reference)));
}
}
@@ -1020,7 +1040,7 @@ public class InferenceSession {
}
public InferenceVariable getInferenceVariable(PsiTypeParameter parameter) {
- return myInferenceVariables.get(parameter);
+ return parameter instanceof InferenceVariable && myInferenceVariables.contains(parameter) ? (InferenceVariable)parameter : null;
}
/**
@@ -1031,10 +1051,11 @@ public class InferenceSession {
PsiExpression[] args,
PsiElement context,
boolean varargs) {
- final InferenceSession session = new InferenceSession(PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY, m2.getManager(), context);
+ List<PsiTypeParameter> params = new ArrayList<PsiTypeParameter>();
for (PsiTypeParameter param : PsiUtil.typeParametersIterable(m2)) {
- session.initBounds(context, param);
+ params.add(param);
}
+ final InferenceSession session = new InferenceSession(params.toArray(new PsiTypeParameter[params.size()]), PsiSubstitutor.EMPTY, m2.getManager(), context);
final PsiParameter[] parameters1 = m1.getParameterList().getParameters();
final PsiParameter[] parameters2 = m2.getParameterList().getParameters();
@@ -1045,7 +1066,7 @@ public class InferenceSession {
final int paramsLength = !varargs ? parameters1.length : parameters1.length - 1;
for (int i = 0; i < paramsLength; i++) {
PsiType sType = getParameterType(parameters1, i, PsiSubstitutor.EMPTY, false);
- PsiType tType = getParameterType(parameters2, i, PsiSubstitutor.EMPTY, varargs);
+ PsiType tType = session.substituteWithInferenceVariables(getParameterType(parameters2, i, PsiSubstitutor.EMPTY, varargs));
if (session.isProperType(sType) && session.isProperType(tType)) {
if (!TypeConversionUtil.isAssignable(tType, sType)) {
return false;
@@ -1063,7 +1084,7 @@ public class InferenceSession {
if (varargs) {
PsiType sType = getParameterType(parameters1, paramsLength, PsiSubstitutor.EMPTY, true);
- PsiType tType = getParameterType(parameters2, paramsLength, PsiSubstitutor.EMPTY, true);
+ PsiType tType = session.substituteWithInferenceVariables(getParameterType(parameters2, paramsLength, PsiSubstitutor.EMPTY, true));
session.addConstraint(new StrictSubtypingConstraint(tType, sType));
}
@@ -1257,25 +1278,6 @@ public class InferenceSession {
return myIncorporationPhase.hasCaptureConstraints(Arrays.asList(inferenceVariable));
}
- public void liftBounds(PsiElement context, Collection<InferenceVariable> variables) {
- for (InferenceVariable variable : variables) {
- final PsiTypeParameter parameter = variable.getParameter();
- final InferenceVariable inferenceVariable = getInferenceVariable(parameter);
- if (inferenceVariable != null) {
- final PsiElement callContext = inferenceVariable.getCallContext();
- if (context.equals(callContext) || myContext.equals(callContext)) {
- for (InferenceBound boundType : InferenceBound.values()) {
- for (PsiType bound : variable.getBounds(boundType)) {
- inferenceVariable.addBound(bound, boundType);
- }
- }
- }
- } else {
- myInferenceVariables.put(parameter, variable);
- }
- }
- }
-
public static boolean wasUncheckedConversionPerformed(PsiElement call) {
final Boolean erased = call.getUserData(ERASED);
return erased != null && erased.booleanValue();
@@ -1284,4 +1286,20 @@ public class InferenceSession {
public PsiElement getContext() {
return myContext;
}
+
+ public void propagateVariables(Collection<InferenceVariable> variables) {
+ myInferenceVariables.addAll(variables);
+ }
+
+ public PsiType substituteWithInferenceVariables(PsiType type) {
+ return myInferenceSubstitution.substitute(type);
+ }
+
+ public PsiType startWithFreshVars(PsiType type) {
+ PsiSubstitutor s = PsiSubstitutor.EMPTY;
+ for (InferenceVariable variable : myInferenceVariables) {
+ s = s.put(variable, JavaPsiFacade.getElementFactory(variable.getProject()).createType(variable.getParameter()));
+ }
+ return s.substitute(type);
+ }
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java
index 6bc9e0b89871..8d91b620f798 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java
@@ -15,9 +15,7 @@
*/
package com.intellij.psi.impl.source.resolve.graphInference;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiType;
-import com.intellij.psi.PsiTypeParameter;
+import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightTypeParameter;
import java.util.*;
@@ -139,6 +137,11 @@ public class InferenceVariable extends LightTypeParameter {
}
@Override
+ public boolean useDelegateToSubstitute() {
+ return false;
+ }
+
+ @Override
public String toString() {
return getDelegate().toString();
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiGraphInferenceHelper.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiGraphInferenceHelper.java
index b4c971b3b469..28ad946275e9 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiGraphInferenceHelper.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiGraphInferenceHelper.java
@@ -67,12 +67,12 @@ public class PsiGraphInferenceHelper implements PsiInferenceHelper {
if (typeParameters.length == 0) return PsiSubstitutor.EMPTY;
InferenceSession session = new InferenceSession(typeParameters, leftTypes, rightTypes, PsiSubstitutor.EMPTY, myManager, null);
for (PsiType leftType : leftTypes) {
- if (!session.isProperType(leftType)) {
+ if (!session.isProperType(session.substituteWithInferenceVariables(leftType))) {
return session.infer();
}
}
for (PsiType rightType : rightTypes) {
- if (!session.isProperType(rightType)) {
+ if (!session.isProperType(session.substituteWithInferenceVariables(rightType))) {
return session.infer();
}
}
@@ -105,10 +105,11 @@ public class PsiGraphInferenceHelper implements PsiInferenceHelper {
rightTypes = new PsiType[]{param};
}
final InferenceSession inferenceSession = new InferenceSession(new PsiTypeParameter[]{typeParam}, leftTypes, rightTypes, PsiSubstitutor.EMPTY, myManager, null);
- if (inferenceSession.isProperType(param) && inferenceSession.isProperType(arg)) {
+ if (inferenceSession.isProperType(inferenceSession.substituteWithInferenceVariables(param)) &&
+ inferenceSession.isProperType(inferenceSession.substituteWithInferenceVariables(arg))) {
boolean proceed = false;
for (PsiClassType classType : typeParam.getExtendsListTypes()) {
- if (!inferenceSession.isProperType(classType)) {
+ if (!inferenceSession.isProperType(inferenceSession.substituteWithInferenceVariables(classType))) {
proceed = true;
break;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
index 82b320ae99f3..b59cf70bdb69 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
@@ -19,16 +19,12 @@ import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable;
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
-import com.intellij.psi.impl.source.tree.java.PsiMethodCallExpressionImpl;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
-import java.util.Collection;
-import java.util.Iterator;
+import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -94,7 +90,11 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
if (method != null && !method.isConstructor()) {
returnType = method.getReturnType();
if (returnType != null) {
- typeParams = method.getTypeParameters();
+ List<PsiTypeParameter> params = new ArrayList<PsiTypeParameter>();
+ for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(method)) {
+ params.add(parameter);
+ }
+ typeParams = params.toArray(new PsiTypeParameter[params.size()]);
}
} else if (myExpression instanceof PsiNewExpression) { //default constructor
final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)myExpression).getClassOrAnonymousClassReference();
@@ -108,38 +108,8 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
}
if (typeParams != null) {
-
- final Set<PsiTypeParameter> oldBounds = ContainerUtil.newHashSet(session.getParamsToInfer());
- final boolean sameMethodCall = session.initBounds(myExpression, typeParams);
- PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
- final HashSet<InferenceVariable> variables = new HashSet<InferenceVariable>();
- session.collectDependencies(returnType, variables);
- final PsiTypeParameter[] params = new PsiTypeParameter[typeParams.length];
- for (int i = 0; i < typeParams.length; i++) {
- if (variables.contains(session.getInferenceVariable(typeParams[i]))) {
- params[i] = JavaPsiFacade.getElementFactory(myExpression.getProject()).createTypeParameterFromText("copyOf" + myExpression.hashCode() + typeParams[i].getName(), null);
- substitutor = substitutor.put(typeParams[i], JavaPsiFacade.getElementFactory(myExpression.getProject()).createType(params[i]));
- }
- else {
- params[i] = typeParams[i];
- }
- }
- PsiSubstitutor siteSubstitutor = PsiSubstitutor.EMPTY;
- if (method != null && !method.isConstructor()) {
- if (resolveResult instanceof MethodCandidateInfo) {
- siteSubstitutor = ((MethodCandidateInfo)resolveResult).getSiteSubstitutor();
- }
- else if (candidateProperties != null) {
- siteSubstitutor = candidateProperties.getSubstitutor();
- }
- }
- for (PsiTypeParameter typeParameter : siteSubstitutor.getSubstitutionMap().keySet()) {
- substitutor = substitutor.put(typeParameter, substitutor.substitute(siteSubstitutor.substitute(typeParameter)));
- }
-
- final Collection<PsiTypeParameter> params1 = session.getTypeParams();
- final InferenceSession callSession = new InferenceSession(params, substitutor, myExpression.getManager(), myExpression);
- callSession.initBounds(session.getContext(), params1.toArray(new PsiTypeParameter[params1.size()]));
+ final InferenceSession callSession = new InferenceSession(typeParams, PsiSubstitutor.EMPTY, myExpression.getManager(), myExpression);
+ callSession.propagateVariables(session.getInferenceVariables());
if (method != null) {
final PsiExpression[] args = argumentList.getExpressions();
final PsiParameter[] parameters = method.getParameterList().getParameters();
@@ -150,27 +120,12 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
if (!accepted) {
return false;
}
- callSession.registerReturnTypeConstraints(
- method != null && !PsiUtil.isRawSubstitutor(method, siteSubstitutor) ? siteSubstitutor.substitute(returnType) : returnType,
- substitutor.substitute(returnType));
+ callSession.registerReturnTypeConstraints(returnType, myT);
if (callSession.repeatInferencePhases(true)) {
- final Collection<InferenceVariable> inferenceVariables = callSession.getInferenceVariables();
- if (sameMethodCall) {
- for (Iterator<InferenceVariable> iterator = inferenceVariables.iterator(); iterator.hasNext(); ) {
- InferenceVariable variable = iterator.next();
- if (oldBounds.contains(variable.getParameter())) {
- iterator.remove();
- }
- }
- }
- session.liftBounds(myExpression, inferenceVariables);
+ session.registerNestedSession(callSession);
} else {
return false;
}
- final PsiType capturedReturnType = myExpression instanceof PsiMethodCallExpression
- ? PsiMethodCallExpressionImpl.captureReturnType((PsiMethodCallExpression)myExpression, method, returnType, substitutor)
- : substitutor.substitute(returnType);
- constraints.add(new TypeCompatibilityConstraint(myT, capturedReturnType));
}
}
return true;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java
index cbed2ea59491..c282481e79c0 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java
@@ -45,7 +45,7 @@ public class LambdaExpressionCompatibilityConstraint implements ConstraintFormul
constraints.add(new StrictSubtypingConstraint(myT, groundTargetType));
} else {
for (PsiParameter parameter : parameters) {
- if (!session.isProperType(substitutor.substitute(parameter.getType()))) {
+ if (!session.isProperType(session.substituteWithInferenceVariables(substitutor.substitute(parameter.getType())))) {
return false;
}
}
@@ -62,7 +62,7 @@ public class LambdaExpressionCompatibilityConstraint implements ConstraintFormul
if (returnExpressions.isEmpty() && !myExpression.isValueCompatible()) { //not value-compatible
return false;
}
- returnType = substitutor.substitute(returnType);
+ returnType = session.substituteWithInferenceVariables(substitutor.substitute(returnType));
if (!session.isProperType(returnType)) {
for (PsiExpression returnExpression : returnExpressions) {
constraints.add(new ExpressionCompatibilityConstraint(returnExpression, returnType));
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java
index eefd040b2a99..fbfd8195fc11 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java
@@ -93,11 +93,13 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
if (targetParameters.length == parameters.length + 1) {
specialCase(session, constraints, substitutor, targetParameters, true);
for (int i = 1; i < targetParameters.length; i++) {
- constraints.add(new TypeCompatibilityConstraint(psiSubstitutor.substitute(parameters[i - 1].getType()), substitutor.substitute(targetParameters[i].getType())));
+ constraints.add(new TypeCompatibilityConstraint(session.substituteWithInferenceVariables(psiSubstitutor.substitute(parameters[i - 1].getType())),
+ substitutor.substitute(targetParameters[i].getType())));
}
} else if (targetParameters.length == parameters.length) {
for (int i = 0; i < targetParameters.length; i++) {
- constraints.add(new TypeCompatibilityConstraint(psiSubstitutor.substitute(parameters[i].getType()), substitutor.substitute(targetParameters[i].getType())));
+ constraints.add(new TypeCompatibilityConstraint(session.substituteWithInferenceVariables(psiSubstitutor.substitute(parameters[i].getType())),
+ substitutor.substitute(targetParameters[i].getType())));
}
} else {
return false;
@@ -108,12 +110,13 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
}
if (applicableMethodReturnType != null) {
- constraints.add(new TypeCompatibilityConstraint(returnType, psiSubstitutor.substitute(applicableMethodReturnType)));
- } else if (applicableMember instanceof PsiClass || applicableMember instanceof PsiMethod && ((PsiMethod)applicableMember).isConstructor()) {
+ constraints.add(new TypeCompatibilityConstraint(returnType,
+ session.substituteWithInferenceVariables(psiSubstitutor.substitute(applicableMethodReturnType))));
+ }
+ else if (applicableMember instanceof PsiClass || applicableMember instanceof PsiMethod && ((PsiMethod)applicableMember).isConstructor()) {
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(applicableMember.getProject());
-
if (containingClass != null) {
- final PsiClassType classType = elementFactory.createType(containingClass, psiSubstitutor);
+ final PsiType classType = session.substituteWithInferenceVariables(elementFactory.createType(containingClass, psiSubstitutor));
constraints.add(new TypeCompatibilityConstraint(returnType, classType));
}
}
@@ -122,7 +125,7 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
}
final Map<PsiMethodReferenceExpression, PsiType> map = PsiMethodReferenceUtil.getFunctionalTypeMap();
- final PsiType added = map.put(myExpression, groundTargetType);
+ final PsiType added = map.put(myExpression, session.startWithFreshVars(groundTargetType));
final JavaResolveResult resolve;
try {
resolve = myExpression.advancedResolve(true);
@@ -205,7 +208,7 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
PsiPolyExpressionUtil.mentionsTypeParameters(referencedMethodReturnType, ContainerUtil.newHashSet(containingClass.getTypeParameters()))) { //todo specification bug?
specialCase(session, constraints, substitutor, targetParameters, false);
}
- constraints.add(new TypeCompatibilityConstraint(returnType, psiSubstitutor.substitute(referencedMethodReturnType)));
+ constraints.add(new TypeCompatibilityConstraint(returnType, session.substituteWithInferenceVariables(psiSubstitutor.substitute(referencedMethodReturnType))));
}
return true;
@@ -241,7 +244,8 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
final PsiClass qualifierClass = PsiUtil.resolveClassInType(qualifierType);
if (qualifierClass != null) {
session.initBounds(qualifierClass.getTypeParameters());
- constraints.add(new StrictSubtypingConstraint(qualifierType, substitutor.substitute(targetParameters[0].getType())));
+ constraints.add(new StrictSubtypingConstraint(session.substituteWithInferenceVariables(qualifierType),
+ session.substituteWithInferenceVariables(substitutor.substitute(targetParameters[0].getType()))));
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java
index 29525add1549..661d59105046 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java
@@ -68,7 +68,7 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
if (interfaceMethod != null) {
final PsiClassType returnType = composeReturnType(containingClass, substitutor);
final InferenceSession session = new InferenceSession(containingClass.getTypeParameters(), substitutor, reference.getManager(), null);
- if (!(session.isProperType(returnType) && session.isProperType(interfaceMethodReturnType))) {
+ if (!(session.isProperType(session.substituteWithInferenceVariables(returnType)) && session.isProperType(interfaceMethodReturnType))) {
session.registerReturnTypeConstraints(returnType, interfaceMethodReturnType);
substitutor = session.infer();
}
@@ -116,13 +116,6 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
private PsiSubstitutor inferTypeArguments() {
if (interfaceMethod == null) return substitutor;
final InferenceSession session = new InferenceSession(method.getTypeParameters(), substitutor, reference.getManager(), reference);
-
- //lift parameters from outer call
- final CurrentCandidateProperties methodSubstitutorPair = MethodCandidateInfo.getCurrentMethod(reference.getParent());
- if (methodSubstitutorPair != null) {
- session.initBounds(methodSubstitutorPair.getMethod().getTypeParameters());
- }
-
final PsiSubstitutor psiSubstitutor = session.collectApplicabilityConstraints(reference, this, functionalInterfaceType);
if (psiSubstitutor != null) {
return psiSubstitutor;
@@ -133,6 +126,10 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
}
if (interfaceMethodReturnType != PsiType.VOID && interfaceMethodReturnType != null) {
+ if (method.isConstructor()) {
+ //todo
+ session.initBounds(reference, method.getContainingClass().getTypeParameters());
+ }
final PsiType returnType = method.isConstructor() ? composeReturnType(containingClass, substitutor) : method.getReturnType();
if (returnType != null) {
session.registerReturnTypeConstraints(returnType, interfaceMethodReturnType);