From e273976e258044cf6fd609f0ff7a555ad663f36a Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 18 Sep 2013 18:51:07 +0400 Subject: [PATCH] new inference: null upper bounds --- .../InferenceIncorporationPhase.java | 4 +- .../graphInference/InferenceSession.java | 95 ++++++++++--------- .../graphInference/InferenceVariable.java | 2 +- .../InferenceVariablesOrder.java | 2 +- .../graphInference/PsiPolyExpressionUtil.java | 3 +- .../constraints/SubtypingConstraint.java | 19 ++-- 6 files changed, 67 insertions(+), 58 deletions(-) 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 68e2f9a3d597..6160bb672eb1 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 @@ -34,7 +34,7 @@ public class InferenceIncorporationPhase { public void incorporate() { for (InferenceVariable inferenceVariable : mySession.getInferenceVariables()) { - if (inferenceVariable.getInstantiation() != null) continue; + if (inferenceVariable.getInstantiation() != PsiType.NULL) continue; final List eqBounds = inferenceVariable.getBounds(InferenceBound.EQ); final List upperBounds = inferenceVariable.getBounds(InferenceBound.UPPER); final List lowerBounds = inferenceVariable.getBounds(InferenceBound.LOWER); @@ -67,7 +67,7 @@ public class InferenceIncorporationPhase { boolean isFullyIncorporated() { boolean needFurtherIncorporation = false; for (InferenceVariable inferenceVariable : mySession.getInferenceVariables()) { - if (inferenceVariable.getInstantiation() != null) continue; + if (inferenceVariable.getInstantiation() != PsiType.NULL) continue; final List eqBounds = inferenceVariable.getBounds(InferenceBound.EQ); final List upperBounds = inferenceVariable.getBounds(InferenceBound.UPPER); final List lowerBounds = inferenceVariable.getBounds(InferenceBound.LOWER); 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 6c2e5c2c8d65..dba4a7289a5e 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 @@ -105,7 +105,7 @@ public class InferenceSession { for (InferenceVariable inferenceVariable : myInferenceVariables.values()) { final PsiTypeParameter typeParameter = inferenceVariable.getParameter(); PsiType instantiation = inferenceVariable.getInstantiation(); - if (instantiation == null) { + if (instantiation == PsiType.NULL) { //failed inference mySiteSubstitutor = mySiteSubstitutor .put(typeParameter, JavaPsiFacade.getInstance(typeParameter.getProject()).getElementFactory().createType(typeParameter)); @@ -161,11 +161,12 @@ public class InferenceSession { return null; } - public boolean isProperType(@NotNull PsiType type) { + public boolean isProperType(@Nullable PsiType type) { return collectDependencies(type, null); } - public boolean collectDependencies(@NotNull PsiType type, @Nullable final Set dependencies) { + public boolean collectDependencies(@Nullable PsiType type, @Nullable final Set dependencies) { + if (type == null) return true; final Boolean isProper = type.accept(new PsiTypeVisitor() { @Nullable @Override @@ -240,58 +241,66 @@ public class InferenceSession { for (List variables : independentVars) { for (InferenceVariable inferenceVariable : variables) { - if (inferenceVariable.getInstantiation() != null) continue; + if (inferenceVariable.getInstantiation() != PsiType.NULL) continue; final PsiTypeParameter typeParameter = inferenceVariable.getParameter(); - PsiType bound = null; - final List eqBounds = inferenceVariable.getBounds(InferenceBound.EQ); - for (PsiType eqBound : eqBounds) { - eqBound = acceptBoundsWithRecursiveDependencies(typeParameter, eqBound); - if (isProperType(eqBound)) { - bound = eqBound; - break; - } - } - if (bound != null) { - inferenceVariable.setInstantiation(bound); - } else { + try { + final List eqBounds = inferenceVariable.getBounds(InferenceBound.EQ); final List lowerBounds = inferenceVariable.getBounds(InferenceBound.LOWER); - PsiType lub = null; - for (PsiType lowerBound : lowerBounds) { - lowerBound = acceptBoundsWithRecursiveDependencies(typeParameter, lowerBound); - if (isProperType(lowerBound)) { - if (lub == null) { - lub = lowerBound; - } - else { - lub = GenericsUtil.getLeastUpperBound(lub, lowerBound, myManager); - } + final List upperBounds = inferenceVariable.getBounds(InferenceBound.UPPER); + if (/*eqBounds.contains(null) || lowerBounds.contains(null) || */upperBounds.contains(null)) { + inferenceVariable.setInstantiation(null); + continue; + } + PsiType bound = null; + for (PsiType eqBound : eqBounds) { + eqBound = acceptBoundsWithRecursiveDependencies(typeParameter, eqBound); + if (isProperType(eqBound)) { + bound = eqBound; + break; } } - if (lub != null) { - inferenceVariable.setInstantiation(lub instanceof PsiCapturedWildcardType ? ((PsiCapturedWildcardType)lub).getWildcard() : lub); - } - else { - PsiType glb = null; - for (PsiType upperBound : inferenceVariable.getBounds(InferenceBound.UPPER)) { - upperBound = acceptBoundsWithRecursiveDependencies(typeParameter, upperBound); - if (isProperType(upperBound)) { - if (glb == null) { - glb = upperBound; + if (bound != null) { + inferenceVariable.setInstantiation(bound); + } else { + PsiType lub = null; + for (PsiType lowerBound : lowerBounds) { + lowerBound = acceptBoundsWithRecursiveDependencies(typeParameter, lowerBound); + if (isProperType(lowerBound)) { + if (lub == null) { + lub = lowerBound; } else { - glb = GenericsUtil.getGreatestLowerBound(glb, upperBound); + lub = GenericsUtil.getLeastUpperBound(lub, lowerBound, myManager); } } } - if (glb != null) { - inferenceVariable.setInstantiation(glb); + if (lub != null) { + inferenceVariable.setInstantiation(lub instanceof PsiCapturedWildcardType ? ((PsiCapturedWildcardType)lub).getWildcard() : lub); + } + else { + PsiType glb = null; + for (PsiType upperBound : upperBounds) { + upperBound = acceptBoundsWithRecursiveDependencies(typeParameter, upperBound); + if (isProperType(upperBound)) { + if (glb == null) { + glb = upperBound; + } + else { + glb = GenericsUtil.getGreatestLowerBound(glb, upperBound); + } + } + } + if (glb != null) { + inferenceVariable.setInstantiation(glb); + } } } } - - final PsiType instantiation = inferenceVariable.getInstantiation(); - if (instantiation != null) { - mySiteSubstitutor = mySiteSubstitutor.put(typeParameter, instantiation); + finally { + final PsiType instantiation = inferenceVariable.getInstantiation(); + if (instantiation != PsiType.NULL) { + mySiteSubstitutor = mySiteSubstitutor.put(typeParameter, instantiation); + } } } } 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 8381295766ab..e69f229fe91f 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 @@ -32,7 +32,7 @@ public class InferenceVariable { private Map> myBounds = new HashMap>(); private PsiTypeParameter myParameter; - private PsiType myInstantiation; + private PsiType myInstantiation = PsiType.NULL; public InferenceVariable(PsiTypeParameter parameter) { myParameter = parameter; } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariablesOrder.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariablesOrder.java index f85bb6d85702..4a2c4126611e 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariablesOrder.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariablesOrder.java @@ -36,7 +36,7 @@ public class InferenceVariablesOrder { } for (InferenceVariable var : vars) { - if (var.getInstantiation() != null) continue; + if (var.getInstantiation() != PsiType.NULL) continue; final InferenceGraphNode node = nodes.get(var); for (InferenceBound inferenceBound : InferenceBound.values()) { for (PsiType bound : var.getBounds(inferenceBound)) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiPolyExpressionUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiPolyExpressionUtil.java index 7a78042012d4..2e425e0fb436 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiPolyExpressionUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiPolyExpressionUtil.java @@ -86,7 +86,8 @@ public class PsiPolyExpressionUtil { return PsiTypesUtil.getExpectedTypeByParent(expression); } - public static Boolean mentionsTypeParameters(PsiType returnType, final Set typeParameters) { + public static Boolean mentionsTypeParameters(@Nullable PsiType returnType, final Set typeParameters) { + if (returnType == null) return false; return returnType.accept(new PsiTypeVisitor() { @Nullable @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/SubtypingConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/SubtypingConstraint.java index 764c672bfbae..64c28d1b462f 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/SubtypingConstraint.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/SubtypingConstraint.java @@ -32,7 +32,7 @@ public class SubtypingConstraint implements ConstraintFormula { private PsiType myT; private boolean myIsRefTypes; - public SubtypingConstraint(@NotNull PsiType t, @NotNull PsiType s, boolean isRefTypes) { + public SubtypingConstraint(PsiType t, PsiType s, boolean isRefTypes) { myT = t; myS = s; myIsRefTypes = isRefTypes; @@ -42,6 +42,7 @@ public class SubtypingConstraint implements ConstraintFormula { public boolean reduce(InferenceSession session, List constraints, List delayedConstraints) { if (myIsRefTypes) { if (session.isProperType(myS) && session.isProperType(myT)) { + if (myT == null || myS == null) return myS == myT; return TypeConversionUtil.isAssignable(myT, myS); } InferenceVariable inferenceVariable = session.getInferenceVariable(myS); @@ -49,7 +50,7 @@ public class SubtypingConstraint implements ConstraintFormula { inferenceVariable.addBound(myT, InferenceBound.UPPER); return true; } - if (myS.equals(PsiType.NULL)) return true; + if (PsiType.NULL.equals(myS)) return true; inferenceVariable = session.getInferenceVariable(myT); if (inferenceVariable != null) { inferenceVariable.addBound(myS, InferenceBound.LOWER); @@ -88,9 +89,7 @@ public class SubtypingConstraint implements ConstraintFormula { for (PsiTypeParameter parameter : CClass.getTypeParameters()) { final PsiType tSubstituted = tSubstitutor.substitute(parameter); final PsiType sSubstituted = sSubstitutor.substituteWithBoundsPromotion(parameter); - if (tSubstituted != null && sSubstituted != null) { - constraints.add(new SubtypingConstraint(tSubstituted, sSubstituted, false)); - } + constraints.add(new SubtypingConstraint(tSubstituted, sSubstituted, false)); } return true; } @@ -105,7 +104,7 @@ public class SubtypingConstraint implements ConstraintFormula { return true; } - if (myT.equals(PsiType.NULL)) return false; + if (PsiType.NULL.equals(myT)) return false; } else { if (myT instanceof PsiWildcardType) { final PsiType tBound = ((PsiWildcardType)myT).getBound(); @@ -160,16 +159,16 @@ public class SubtypingConstraint implements ConstraintFormula { SubtypingConstraint that = (SubtypingConstraint)o; if (myIsRefTypes != that.myIsRefTypes) return false; - if (!myS.equals(that.myS)) return false; - if (!myT.equals(that.myT)) return false; + if (myS != null ? !myS.equals(that.myS) : that.myS != null) return false; + if (myT != null ? !myT.equals(that.myT) : that.myT != null) return false; return true; } @Override public int hashCode() { - int result = myS.hashCode(); - result = 31 * result + myT.hashCode(); + int result = myS != null ? myS.hashCode() : 0; + result = 31 * result + (myT != null ? myT.hashCode() : 0); result = 31 * result + (myIsRefTypes ? 1 : 0); return result; }