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