mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
new inference: null upper bounds
This commit is contained in:
+2
-2
@@ -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<PsiType> eqBounds = inferenceVariable.getBounds(InferenceBound.EQ);
|
||||
final List<PsiType> upperBounds = inferenceVariable.getBounds(InferenceBound.UPPER);
|
||||
final List<PsiType> 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<PsiType> eqBounds = inferenceVariable.getBounds(InferenceBound.EQ);
|
||||
final List<PsiType> upperBounds = inferenceVariable.getBounds(InferenceBound.UPPER);
|
||||
final List<PsiType> lowerBounds = inferenceVariable.getBounds(InferenceBound.LOWER);
|
||||
|
||||
+52
-43
@@ -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<InferenceVariable> dependencies) {
|
||||
public boolean collectDependencies(@Nullable PsiType type, @Nullable final Set<InferenceVariable> dependencies) {
|
||||
if (type == null) return true;
|
||||
final Boolean isProper = type.accept(new PsiTypeVisitor<Boolean>() {
|
||||
@Nullable
|
||||
@Override
|
||||
@@ -240,58 +241,66 @@ public class InferenceSession {
|
||||
for (List<InferenceVariable> 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<PsiType> 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<PsiType> eqBounds = inferenceVariable.getBounds(InferenceBound.EQ);
|
||||
final List<PsiType> 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<PsiType> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ public class InferenceVariable {
|
||||
private Map<InferenceBound, List<PsiType>> myBounds = new HashMap<InferenceBound, List<PsiType>>();
|
||||
private PsiTypeParameter myParameter;
|
||||
|
||||
private PsiType myInstantiation;
|
||||
private PsiType myInstantiation = PsiType.NULL;
|
||||
public InferenceVariable(PsiTypeParameter parameter) {
|
||||
myParameter = parameter;
|
||||
}
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ public class InferenceVariablesOrder {
|
||||
}
|
||||
|
||||
for (InferenceVariable var : vars) {
|
||||
if (var.getInstantiation() != null) continue;
|
||||
if (var.getInstantiation() != PsiType.NULL) continue;
|
||||
final InferenceGraphNode<InferenceVariable> node = nodes.get(var);
|
||||
for (InferenceBound inferenceBound : InferenceBound.values()) {
|
||||
for (PsiType bound : var.getBounds(inferenceBound)) {
|
||||
|
||||
+2
-1
@@ -86,7 +86,8 @@ public class PsiPolyExpressionUtil {
|
||||
return PsiTypesUtil.getExpectedTypeByParent(expression);
|
||||
}
|
||||
|
||||
public static Boolean mentionsTypeParameters(PsiType returnType, final Set<PsiTypeParameter> typeParameters) {
|
||||
public static Boolean mentionsTypeParameters(@Nullable PsiType returnType, final Set<PsiTypeParameter> typeParameters) {
|
||||
if (returnType == null) return false;
|
||||
return returnType.accept(new PsiTypeVisitor<Boolean>() {
|
||||
@Nullable
|
||||
@Override
|
||||
|
||||
+9
-10
@@ -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<ConstraintFormula> constraints, List<ConstraintFormula> 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user