TypeConstraints -> TypeBounds
This commit is contained in:
Svetlana Isakova
2013-09-27 14:56:55 +04:00
parent 65e2f47bc3
commit 0e507e6b40
7 changed files with 120 additions and 122 deletions
@@ -246,7 +246,7 @@ public class Renderers {
TabledDescriptorRenderer renderer) {
TypeParameterDescriptor firstUnknownParameter = null;
for (TypeParameterDescriptor typeParameter : inferenceErrorData.constraintSystem.getTypeVariables()) {
if (inferenceErrorData.constraintSystem.getTypeConstraints(typeParameter).isEmpty()) {
if (inferenceErrorData.constraintSystem.getTypeBounds(typeParameter).isEmpty()) {
firstUnknownParameter = typeParameter;
break;
}
@@ -278,7 +278,7 @@ public class Renderers {
}
assert typeParameterDescriptor != null : errorMessage;
JetType inferredValueForTypeParameter = systemWithoutWeakConstraints.getTypeConstraints(typeParameterDescriptor).getValue();
JetType inferredValueForTypeParameter = systemWithoutWeakConstraints.getTypeBounds(typeParameterDescriptor).getValue();
assert inferredValueForTypeParameter != null : errorMessage;
result.text(newText().normal("Type parameter bound for ").strong(typeParameterDescriptor.getName()).normal(" in "))
@@ -112,7 +112,7 @@ public class CallResolverUtil {
if (returnType == null) return false;
for (TypeParameterDescriptor typeVariable : constraintSystem.getTypeVariables()) {
JetType inferredValueForTypeVariable = constraintSystem.getTypeConstraints(typeVariable).getValue();
JetType inferredValueForTypeVariable = constraintSystem.getTypeBounds(typeVariable).getValue();
if (inferredValueForTypeVariable == null) {
if (TypeUtils.dependsOnTypeParameters(returnType, Collections.singleton(typeVariable))) {
return true;
@@ -18,7 +18,6 @@ package org.jetbrains.jet.lang.resolve.calls.inference;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
@@ -31,7 +30,7 @@ public class ConstraintsUtil {
@Nullable
public static TypeParameterDescriptor getFirstConflictingParameter(@NotNull ConstraintSystem constraintSystem) {
for (TypeParameterDescriptor typeParameter : constraintSystem.getTypeVariables()) {
TypeConstraints constraints = constraintSystem.getTypeConstraints(typeParameter);
TypeBounds constraints = constraintSystem.getTypeBounds(typeParameter);
if (constraints.getValues().size() > 1) {
return typeParameter;
}
@@ -44,7 +43,7 @@ public class ConstraintsUtil {
TypeParameterDescriptor firstConflictingParameter = getFirstConflictingParameter(constraintSystem);
if (firstConflictingParameter == null) return Collections.emptyList();
Collection<JetType> conflictingTypes = constraintSystem.getTypeConstraints(firstConflictingParameter).getValues();
Collection<JetType> conflictingTypes = constraintSystem.getTypeBounds(firstConflictingParameter).getValues();
ArrayList<Map<TypeConstructor, TypeProjection>> substitutionContexts = Lists.newArrayList();
for (JetType type : conflictingTypes) {
@@ -71,7 +70,7 @@ public class ConstraintsUtil {
@NotNull
public static JetType getSafeValue(@NotNull ConstraintSystem constraintSystem, @NotNull TypeParameterDescriptor typeParameter) {
JetType type = constraintSystem.getTypeConstraints(typeParameter).getValue();
JetType type = constraintSystem.getTypeBounds(typeParameter).getValue();
if (type != null) {
return type;
}
@@ -84,7 +83,7 @@ public class ConstraintsUtil {
@NotNull TypeParameterDescriptor typeParameter,
boolean substituteOtherTypeParametersInBound
) {
JetType type = constraintSystem.getTypeConstraints(typeParameter).getValue();
JetType type = constraintSystem.getTypeBounds(typeParameter).getValue();
if (type == null) return true;
for (JetType upperBound : typeParameter.getUpperBounds()) {
if (!substituteOtherTypeParametersInBound && TypeUtils.dependsOnTypeParameters(upperBound, constraintSystem.getTypeVariables())) {
@@ -65,7 +65,7 @@ public interface ConstraintSystem {
* Returns null if the type variable was not registered.
*/
@NotNull
TypeConstraints getTypeConstraints(@NotNull TypeParameterDescriptor typeVariable);
TypeBounds getTypeBounds(@NotNull TypeParameterDescriptor typeVariable);
/**
* Returns a result of solving the constraint system (mapping from the type variable to the resulting type projection). <p/>
@@ -41,9 +41,8 @@ import java.util.Set;
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.EQUAL;
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.SUB_TYPE;
import static org.jetbrains.jet.lang.resolve.calls.inference.TypeConstraintsImpl.BoundKind;
import static org.jetbrains.jet.lang.resolve.calls.inference.TypeConstraintsImpl.BoundKind.*;
import static org.jetbrains.jet.lang.resolve.calls.inference.TypeConstraintsImpl.Constraint;
import static org.jetbrains.jet.lang.resolve.calls.inference.TypeBoundsImpl.BoundKind.*;
import static org.jetbrains.jet.lang.resolve.calls.inference.TypeBoundsImpl.Bound;
import static org.jetbrains.jet.lang.types.TypeUtils.CANT_INFER_TYPE_PARAMETER;
import static org.jetbrains.jet.lang.types.TypeUtils.DONT_CARE;
@@ -53,7 +52,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
SUB_TYPE, EQUAL
}
private final Map<TypeParameterDescriptor, TypeConstraintsImpl> typeParameterConstraints = Maps.newLinkedHashMap();
private final Map<TypeParameterDescriptor, TypeBoundsImpl> typeParameterBounds = Maps.newLinkedHashMap();
private final Set<ConstraintPosition> errorConstraintPositions = Sets.newHashSet();
private final TypeSubstitutor resultingSubstitutor;
private final TypeSubstitutor currentSubstitutor;
@@ -82,16 +81,16 @@ public class ConstraintSystemImpl implements ConstraintSystem {
@Override
public boolean hasConflictingConstraints() {
for (TypeConstraintsImpl typeConstraints : typeParameterConstraints.values()) {
if (typeConstraints.getValues().size() > 1) return true;
for (TypeBoundsImpl typeBounds : typeParameterBounds.values()) {
if (typeBounds.getValues().size() > 1) return true;
}
return false;
}
@Override
public boolean hasUnknownParameters() {
for (TypeConstraintsImpl typeConstraints : typeParameterConstraints.values()) {
if (typeConstraints.isEmpty()) {
for (TypeBoundsImpl typeBounds : typeParameterBounds.values()) {
if (typeBounds.isEmpty()) {
return true;
}
}
@@ -145,8 +144,8 @@ public class ConstraintSystemImpl implements ConstraintSystem {
if (declarationDescriptor instanceof TypeParameterDescriptor) {
TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor;
if (typeParameterConstraints.containsKey(descriptor)) {
JetType value = getTypeConstraints(descriptor).getValue();
if (typeParameterBounds.containsKey(descriptor)) {
JetType value = getTypeBounds(descriptor).getValue();
if (value != null && !TypeUtils.equalsOrContainsAsArgument(value, TypeUtils.DONT_CARE)) {
return new TypeProjection(value);
}
@@ -163,7 +162,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
@Override
public String toString() {
return typeParameterConstraints.toString();
return typeParameterBounds.toString();
}
});
}
@@ -179,18 +178,18 @@ public class ConstraintSystemImpl implements ConstraintSystem {
for (Map.Entry<TypeParameterDescriptor, Variance> entry : typeVariables.entrySet()) {
TypeParameterDescriptor typeVariable = entry.getKey();
Variance positionVariance = entry.getValue();
typeParameterConstraints.put(typeVariable, new TypeConstraintsImpl(typeVariable, positionVariance));
typeParameterBounds.put(typeVariable, new TypeBoundsImpl(typeVariable, positionVariance));
}
TypeSubstitutor constantSubstitutor = TypeUtils.makeConstantSubstitutor(typeParameterConstraints.keySet(), DONT_CARE);
for (Map.Entry<TypeParameterDescriptor, TypeConstraintsImpl> entry : typeParameterConstraints.entrySet()) {
TypeSubstitutor constantSubstitutor = TypeUtils.makeConstantSubstitutor(typeParameterBounds.keySet(), DONT_CARE);
for (Map.Entry<TypeParameterDescriptor, TypeBoundsImpl> entry : typeParameterBounds.entrySet()) {
TypeParameterDescriptor typeVariable = entry.getKey();
TypeConstraintsImpl typeConstraints = entry.getValue();
TypeBoundsImpl typeBounds = entry.getValue();
for (JetType declaredUpperBound : typeVariable.getUpperBounds()) {
if (KotlinBuiltIns.getInstance().getNullableAnyType().equals(declaredUpperBound)) continue; //todo remove this line (?)
JetType substitutedBound = constantSubstitutor.substitute(declaredUpperBound, Variance.INVARIANT);
if (substitutedBound != null) {
typeConstraints.addConstraint(UPPER_BOUND, substitutedBound, ConstraintPosition.getTypeBoundPosition(typeVariable.getIndex()));
typeBounds.addBound(UPPER_BOUND, substitutedBound, ConstraintPosition.getTypeBoundPosition(typeVariable.getIndex()));
}
}
}
@@ -200,10 +199,10 @@ public class ConstraintSystemImpl implements ConstraintSystem {
@NotNull
public ConstraintSystem copy() {
return replaceTypeVariables(Functions.<TypeParameterDescriptor>identity(),
new Function<TypeConstraintsImpl, TypeConstraintsImpl>() {
new Function<TypeBoundsImpl, TypeBoundsImpl>() {
@Override
public TypeConstraintsImpl apply(TypeConstraintsImpl typeConstraints) {
return typeConstraints.copy();
public TypeBoundsImpl apply(TypeBoundsImpl typeBounds) {
return typeBounds.copy();
}
},
Conditions.<ConstraintPosition>alwaysTrue());
@@ -212,17 +211,17 @@ public class ConstraintSystemImpl implements ConstraintSystem {
@NotNull
public ConstraintSystem replaceTypeVariables(@NotNull Function<TypeParameterDescriptor, TypeParameterDescriptor> typeVariablesMap) {
return replaceTypeVariables(typeVariablesMap,
Functions.<TypeConstraintsImpl>identity(),
Functions.<TypeBoundsImpl>identity(),
Conditions.<ConstraintPosition>alwaysTrue());
}
@NotNull
public ConstraintSystem filterConstrains(@NotNull final Condition<ConstraintPosition> condition) {
public ConstraintSystem filterConstraints(@NotNull final Condition<ConstraintPosition> condition) {
return replaceTypeVariables(Functions.<TypeParameterDescriptor>identity(),
new Function<TypeConstraintsImpl, TypeConstraintsImpl>() {
new Function<TypeBoundsImpl, TypeBoundsImpl>() {
@Override
public TypeConstraintsImpl apply(TypeConstraintsImpl typeConstraints) {
return typeConstraints.filter(condition);
public TypeBoundsImpl apply(TypeBoundsImpl typeBounds) {
return typeBounds.filter(condition);
}
},
condition);
@@ -230,7 +229,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
@NotNull
public ConstraintSystem getSystemWithoutWeakConstraints() {
return filterConstrains(new Condition<ConstraintPosition>() {
return filterConstraints(new Condition<ConstraintPosition>() {
@Override
public boolean value(ConstraintPosition constraintPosition) {
// 'isStrong' for compound means 'has some strong constraints'
@@ -248,18 +247,18 @@ public class ConstraintSystemImpl implements ConstraintSystem {
@NotNull
private ConstraintSystem replaceTypeVariables(
@NotNull Function<TypeParameterDescriptor, TypeParameterDescriptor> typeVariablesMap,
@NotNull Function<TypeConstraintsImpl, TypeConstraintsImpl> typeConstraintsMap,
@NotNull Function<TypeBoundsImpl, TypeBoundsImpl> typeBoundsMap,
@NotNull Condition<ConstraintPosition> constraintPositionCondition
) {
ConstraintSystemImpl newConstraintSystem = new ConstraintSystemImpl();
for (Map.Entry<TypeParameterDescriptor, TypeConstraintsImpl> entry : typeParameterConstraints.entrySet()) {
for (Map.Entry<TypeParameterDescriptor, TypeBoundsImpl> entry : typeParameterBounds.entrySet()) {
TypeParameterDescriptor typeParameter = entry.getKey();
TypeConstraintsImpl typeConstraints = entry.getValue();
TypeBoundsImpl typeBounds = entry.getValue();
TypeParameterDescriptor newTypeParameter = typeVariablesMap.apply(typeParameter);
assert newTypeParameter != null;
newConstraintSystem.typeParameterConstraints.put(newTypeParameter, typeConstraintsMap.apply(typeConstraints));
newConstraintSystem.typeParameterBounds.put(newTypeParameter, typeBoundsMap.apply(typeBounds));
}
newConstraintSystem.errorConstraintPositions.addAll(ContainerUtil.filter(errorConstraintPositions, constraintPositionCondition));
newConstraintSystem.hasErrorInConstrainingTypes = hasErrorInConstrainingTypes;
@@ -400,14 +399,14 @@ public class ConstraintSystemImpl implements ConstraintSystem {
private void generateTypeParameterConstraint(
@NotNull JetType parameterType,
@NotNull JetType constrainingType,
@NotNull BoundKind boundKind,
@NotNull TypeBoundsImpl.BoundKind boundKind,
@NotNull ConstraintPosition constraintPosition
) {
TypeConstraintsImpl typeConstraints = getTypeConstraints(parameterType);
assert typeConstraints != null : "constraint should be generated only for type variables";
TypeBoundsImpl typeBounds = getTypeBounds(parameterType);
assert typeBounds != null : "constraint should be generated only for type variables";
if (!parameterType.isNullable() || !constrainingType.isNullable()) {
typeConstraints.addConstraint(boundKind, constrainingType, constraintPosition);
typeBounds.addBound(boundKind, constrainingType, constraintPosition);
return;
}
// For parameter type T:
@@ -415,36 +414,36 @@ public class ConstraintSystemImpl implements ConstraintSystem {
// constraint T? >: Int? should transform to T >: Int
JetType notNullConstrainingType = TypeUtils.makeNotNullable(constrainingType);
if (boundKind == EXACT_BOUND || boundKind == LOWER_BOUND) {
typeConstraints.addConstraint(LOWER_BOUND, notNullConstrainingType, constraintPosition);
typeBounds.addBound(LOWER_BOUND, notNullConstrainingType, constraintPosition);
}
// constraint T? <: Int? should transform to T <: Int?
if (boundKind == EXACT_BOUND || boundKind == UPPER_BOUND) {
typeConstraints.addConstraint(UPPER_BOUND, constrainingType, constraintPosition);
typeBounds.addBound(UPPER_BOUND, constrainingType, constraintPosition);
}
}
public void processDeclaredBoundConstraints() {
for (Map.Entry<TypeParameterDescriptor, TypeConstraintsImpl> entry : typeParameterConstraints.entrySet()) {
for (Map.Entry<TypeParameterDescriptor, TypeBoundsImpl> entry : typeParameterBounds.entrySet()) {
TypeParameterDescriptor typeParameterDescriptor = entry.getKey();
TypeConstraintsImpl typeConstraints = entry.getValue();
TypeBoundsImpl typeBounds = entry.getValue();
for (JetType declaredUpperBound : typeParameterDescriptor.getUpperBounds()) {
//todo order matters here
Collection<Constraint> constraints = Lists.newArrayList(typeConstraints.getConstraints());
for (Constraint constraint : constraints) {
if (constraint.boundKind == LOWER_BOUND || constraint.boundKind == EXACT_BOUND) {
Collection<Bound> bounds = Lists.newArrayList(typeBounds.getBounds());
for (Bound bound : bounds) {
if (bound.kind == LOWER_BOUND || bound.kind == EXACT_BOUND) {
ConstraintPosition position = ConstraintPosition.getCompoundConstraintPosition(
ConstraintPosition.getTypeBoundPosition(typeParameterDescriptor.getIndex()), constraint.constraintPosition);
addSubtypeConstraint(constraint.type, declaredUpperBound, position);
ConstraintPosition.getTypeBoundPosition(typeParameterDescriptor.getIndex()), bound.position);
addSubtypeConstraint(bound.type, declaredUpperBound, position);
}
}
ClassifierDescriptor declarationDescriptor = declaredUpperBound.getConstructor().getDeclarationDescriptor();
if (declarationDescriptor instanceof TypeParameterDescriptor && typeParameterConstraints.containsKey(declarationDescriptor)) {
TypeConstraintsImpl typeConstraintsForUpperBound = typeParameterConstraints.get(declarationDescriptor);
for (Constraint constraint : typeConstraintsForUpperBound.getConstraints()) {
if (constraint.boundKind == UPPER_BOUND || constraint.boundKind == EXACT_BOUND) {
if (declarationDescriptor instanceof TypeParameterDescriptor && typeParameterBounds.containsKey(declarationDescriptor)) {
TypeBoundsImpl typeBoundsForUpperBound = typeParameterBounds.get(declarationDescriptor);
for (Bound bound : typeBoundsForUpperBound.getBounds()) {
if (bound.kind == UPPER_BOUND || bound.kind == EXACT_BOUND) {
ConstraintPosition position = ConstraintPosition.getCompoundConstraintPosition(
ConstraintPosition.getTypeBoundPosition(typeParameterDescriptor.getIndex()), constraint.constraintPosition);
typeConstraints.addConstraint(UPPER_BOUND, constraint.type, position);
ConstraintPosition.getTypeBoundPosition(typeParameterDescriptor.getIndex()), bound.position);
typeBounds.addBound(UPPER_BOUND, bound.type, position);
}
}
}
@@ -455,29 +454,29 @@ public class ConstraintSystemImpl implements ConstraintSystem {
@NotNull
@Override
public Set<TypeParameterDescriptor> getTypeVariables() {
return typeParameterConstraints.keySet();
return typeParameterBounds.keySet();
}
@Override
@NotNull
public TypeConstraints getTypeConstraints(@NotNull TypeParameterDescriptor typeVariable) {
TypeConstraintsImpl typeConstraints = typeParameterConstraints.get(typeVariable);
assert typeConstraints != null : "TypeParameterDescriptor is not a type variable for constraint system: " + typeVariable;
return typeConstraints;
public TypeBounds getTypeBounds(@NotNull TypeParameterDescriptor typeVariable) {
TypeBoundsImpl typeBounds = typeParameterBounds.get(typeVariable);
assert typeBounds != null : "TypeParameterDescriptor is not a type variable for constraint system: " + typeVariable;
return typeBounds;
}
@Nullable
private TypeConstraintsImpl getTypeConstraints(@NotNull JetType type) {
private TypeBoundsImpl getTypeBounds(@NotNull JetType type) {
ClassifierDescriptor parameterDescriptor = type.getConstructor().getDeclarationDescriptor();
if (parameterDescriptor instanceof TypeParameterDescriptor) {
return typeParameterConstraints.get(parameterDescriptor);
return typeParameterBounds.get(parameterDescriptor);
}
return null;
}
private boolean isMyTypeVariable(@NotNull JetType type) {
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
return descriptor instanceof TypeParameterDescriptor && typeParameterConstraints.get(descriptor) != null;
return descriptor instanceof TypeParameterDescriptor && typeParameterBounds.get(descriptor) != null;
}
@NotNull
@@ -24,7 +24,7 @@ import org.jetbrains.jet.lang.types.Variance;
import java.util.Collection;
import java.util.Set;
public interface TypeConstraints {
public interface TypeBounds {
@NotNull
Variance getVarianceOfPosition();
@@ -31,30 +31,30 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Set;
public class TypeConstraintsImpl implements TypeConstraints {
public class TypeBoundsImpl implements TypeBounds {
public static enum BoundKind {
LOWER_BOUND, UPPER_BOUND, EXACT_BOUND
}
public static class Constraint {
public static class Bound {
public final JetType type;
public final BoundKind boundKind;
public final ConstraintPosition constraintPosition;
public final BoundKind kind;
public final ConstraintPosition position;
public Constraint(@NotNull JetType type, @NotNull BoundKind boundKind, @NotNull ConstraintPosition constraintPosition) {
public Bound(@NotNull JetType type, @NotNull BoundKind kind, @NotNull ConstraintPosition position) {
this.type = type;
this.boundKind = boundKind;
this.constraintPosition = constraintPosition;
this.kind = kind;
this.position = position;
}
}
private final TypeParameterDescriptor typeVariable;
private final Variance varianceOfPosition;
private final Set<Constraint> constraints = Sets.newLinkedHashSet();
private final Set<Bound> bounds = Sets.newLinkedHashSet();
private Collection<JetType> resultValues;
public TypeConstraintsImpl(
public TypeBoundsImpl(
@NotNull TypeParameterDescriptor typeVariable,
@NotNull Variance varianceOfPosition
) {
@@ -68,9 +68,9 @@ public class TypeConstraintsImpl implements TypeConstraints {
return varianceOfPosition;
}
public void addConstraint(@NotNull BoundKind boundKind, @NotNull JetType type, @NotNull ConstraintPosition constraintPosition) {
public void addBound(@NotNull BoundKind kind, @NotNull JetType type, @NotNull ConstraintPosition position) {
resultValues = null;
constraints.add(new Constraint(type, boundKind, constraintPosition));
bounds.add(new Bound(type, kind, position));
}
@Override
@@ -79,52 +79,52 @@ public class TypeConstraintsImpl implements TypeConstraints {
}
@NotNull
public Collection<Constraint> getConstraints() {
return constraints;
public Collection<Bound> getBounds() {
return bounds;
}
@NotNull
private static Set<JetType> filterBounds(
@NotNull Collection<Constraint> constraints,
@NotNull BoundKind boundKind
@NotNull Collection<Bound> bounds,
@NotNull BoundKind kind
) {
return filterBounds(constraints, boundKind, null);
return filterBounds(bounds, kind, null);
}
@NotNull
private static Set<JetType> filterBounds(
@NotNull Collection<Constraint> constraints,
@NotNull BoundKind boundKind,
@NotNull Collection<Bound> bounds,
@NotNull BoundKind kind,
@Nullable Collection<JetType> errorValues
) {
Set<JetType> result = Sets.newLinkedHashSet();
for (Constraint constraint : constraints) {
if (constraint.boundKind == boundKind) {
if (!ErrorUtils.containsErrorType(constraint.type)) {
result.add(constraint.type);
for (Bound bound : bounds) {
if (bound.kind == kind) {
if (!ErrorUtils.containsErrorType(bound.type)) {
result.add(bound.type);
}
else if (errorValues != null) {
errorValues.add(constraint.type);
errorValues.add(bound.type);
}
}
}
return result;
}
/*package*/ TypeConstraintsImpl copy() {
TypeConstraintsImpl typeConstraints = new TypeConstraintsImpl(typeVariable, varianceOfPosition);
typeConstraints.constraints.addAll(constraints);
typeConstraints.resultValues = resultValues;
return typeConstraints;
/*package*/ TypeBoundsImpl copy() {
TypeBoundsImpl typeBounds = new TypeBoundsImpl(typeVariable, varianceOfPosition);
typeBounds.bounds.addAll(bounds);
typeBounds.resultValues = resultValues;
return typeBounds;
}
@NotNull
public TypeConstraintsImpl filter(@NotNull final Condition<ConstraintPosition> condition) {
TypeConstraintsImpl result = new TypeConstraintsImpl(typeVariable, varianceOfPosition);
result.constraints.addAll(ContainerUtil.filter(constraints, new Condition<Constraint>() {
public TypeBoundsImpl filter(@NotNull final Condition<ConstraintPosition> condition) {
TypeBoundsImpl result = new TypeBoundsImpl(typeVariable, varianceOfPosition);
result.bounds.addAll(ContainerUtil.filter(bounds, new Condition<Bound>() {
@Override
public boolean value(Constraint constraint) {
return condition.value(constraint.constraintPosition);
public boolean value(Bound bound) {
return condition.value(bound.position);
}
}));
return result;
@@ -144,51 +144,51 @@ public class TypeConstraintsImpl implements TypeConstraints {
@Override
public Collection<JetType> getValues() {
if (resultValues == null) {
resultValues = computeValues(constraints);
resultValues = computeValues(bounds);
}
return resultValues;
}
@NotNull
private static Collection<JetType> computeValues(@NotNull Collection<Constraint> constraints) {
private static Collection<JetType> computeValues(@NotNull Collection<Bound> bounds) {
Set<JetType> values = Sets.newLinkedHashSet();
if (constraints.isEmpty()) {
if (bounds.isEmpty()) {
return Collections.emptyList();
}
boolean hasStrongConstraint = ContainerUtil.exists(constraints, new Condition<Constraint>() {
boolean hasStrongBound = ContainerUtil.exists(bounds, new Condition<Bound>() {
@Override
public boolean value(Constraint constraint) {
return constraint.constraintPosition.isStrong();
public boolean value(Bound bound) {
return bound.position.isStrong();
}
});
if (!hasStrongConstraint) {
if (!hasStrongBound) {
return Collections.emptyList();
}
Set<JetType> exactBounds = filterBounds(constraints, BoundKind.EXACT_BOUND, values);
Set<JetType> exactBounds = filterBounds(bounds, BoundKind.EXACT_BOUND, values);
if (exactBounds.size() == 1) {
JetType exactBound = exactBounds.iterator().next();
if (trySuggestion(exactBound, constraints)) {
if (trySuggestion(exactBound, bounds)) {
return Collections.singleton(exactBound);
}
}
values.addAll(exactBounds);
Pair<Collection<JetType>, Collection<JetType>> pair =
TypeUtils.filterNumberTypes(filterBounds(constraints, BoundKind.LOWER_BOUND, values));
TypeUtils.filterNumberTypes(filterBounds(bounds, BoundKind.LOWER_BOUND, values));
Collection<JetType> generalLowerBounds = pair.getFirst();
Collection<JetType> numberLowerBounds = pair.getSecond();
JetType superTypeOfLowerBounds = CommonSupertypes.commonSupertypeForNonDenotableTypes(generalLowerBounds);
if (trySuggestion(superTypeOfLowerBounds, constraints)) {
if (trySuggestion(superTypeOfLowerBounds, bounds)) {
return Collections.singleton(superTypeOfLowerBounds);
}
ContainerUtil.addIfNotNull(superTypeOfLowerBounds, values);
Set<JetType> upperBounds = filterBounds(constraints, BoundKind.UPPER_BOUND, values);
Set<JetType> upperBounds = filterBounds(bounds, BoundKind.UPPER_BOUND, values);
JetType intersectionOfUpperBounds = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds);
if (!upperBounds.isEmpty() && intersectionOfUpperBounds != null) {
if (trySuggestion(intersectionOfUpperBounds, constraints)) {
if (trySuggestion(intersectionOfUpperBounds, bounds)) {
return Collections.singleton(intersectionOfUpperBounds);
}
}
@@ -196,10 +196,10 @@ public class TypeConstraintsImpl implements TypeConstraints {
//fun <T> foo(t: T, consumer: Consumer<T>): T
//foo(1, c: Consumer<Any>) - infer Int, not Any here
values.addAll(filterBounds(constraints, BoundKind.UPPER_BOUND));
values.addAll(filterBounds(bounds, BoundKind.UPPER_BOUND));
JetType superTypeOfNumberLowerBounds = TypeUtils.commonSupertypeForNumberTypes(numberLowerBounds);
if (trySuggestion(superTypeOfNumberLowerBounds, constraints)) {
if (trySuggestion(superTypeOfNumberLowerBounds, bounds)) {
return Collections.singleton(superTypeOfNumberLowerBounds);
}
ContainerUtil.addIfNotNull(superTypeOfNumberLowerBounds, values);
@@ -207,7 +207,7 @@ public class TypeConstraintsImpl implements TypeConstraints {
if (superTypeOfLowerBounds != null && superTypeOfNumberLowerBounds != null) {
JetType superTypeOfAllLowerBounds = CommonSupertypes.commonSupertypeForNonDenotableTypes(
Lists.newArrayList(superTypeOfLowerBounds, superTypeOfNumberLowerBounds));
if (trySuggestion(superTypeOfAllLowerBounds, constraints)) {
if (trySuggestion(superTypeOfAllLowerBounds, bounds)) {
return Collections.singleton(superTypeOfAllLowerBounds);
}
}
@@ -216,28 +216,28 @@ public class TypeConstraintsImpl implements TypeConstraints {
private static boolean trySuggestion(
@Nullable JetType suggestion,
@NotNull Collection<Constraint> constraints
@NotNull Collection<Bound> bounds
) {
if (suggestion == null) return false;
if (!suggestion.getConstructor().isDenotable()) return false;
if (filterBounds(constraints, BoundKind.EXACT_BOUND).size() > 1) return false;
if (filterBounds(bounds, BoundKind.EXACT_BOUND).size() > 1) return false;
for (Constraint constraint : constraints) {
switch (constraint.boundKind) {
for (Bound bound : bounds) {
switch (bound.kind) {
case LOWER_BOUND:
if (!JetTypeChecker.INSTANCE.isSubtypeOf(constraint.type, suggestion)) {
if (!JetTypeChecker.INSTANCE.isSubtypeOf(bound.type, suggestion)) {
return false;
}
break;
case UPPER_BOUND:
if (!JetTypeChecker.INSTANCE.isSubtypeOf(suggestion, constraint.type)) {
if (!JetTypeChecker.INSTANCE.isSubtypeOf(suggestion, bound.type)) {
return false;
}
break;
case EXACT_BOUND:
if (!JetTypeChecker.INSTANCE.equalTypes(constraint.type, suggestion)) {
if (!JetTypeChecker.INSTANCE.equalTypes(bound.type, suggestion)) {
return false;
}
break;