Constraint priorities introduced. Not used for the time being

This commit is contained in:
Andrey Breslav
2011-12-09 18:15:05 +04:00
parent 3ea077bb43
commit 8e10536ef9
5 changed files with 94 additions and 10 deletions
@@ -29,6 +29,9 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.calls.ResolutionStatus.*;
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl.MAP_TO_CANDIDATE;
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl.MAP_TO_RESULT;
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType.EXPECTED_TYPE;
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType.RECEIVER;
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType.VALUE_ARGUMENT;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
@@ -465,7 +468,7 @@ public class CallResolver {
ExpressionTypingServices temporaryServices = new ExpressionTypingServices(semanticServices, traceForUnknown);
JetType type = temporaryServices.getType(scope, expression, substituteDontCare.substitute(valueParameterDescriptor.getOutType(), Variance.INVARIANT));
if (type != null) {
constraintSystem.addSubtypingConstraint(type, effectiveExpectedType);
constraintSystem.addSubtypingConstraint(VALUE_ARGUMENT.assertSubtyping(type, effectiveExpectedType));
}
else {
candidateCall.argumentHasNoType();
@@ -478,12 +481,12 @@ public class CallResolver {
ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
ReceiverDescriptor receiverParameter = candidateWithFreshVariables.getReceiverParameter();
if (receiverArgument.exists() && receiverParameter.exists()) {
constraintSystem.addSubtypingConstraint(receiverArgument.getType(), receiverParameter.getType());
constraintSystem.addSubtypingConstraint(RECEIVER.assertSubtyping(receiverArgument.getType(), receiverParameter.getType()));
}
// Return type
if (expectedType != NO_EXPECTED_TYPE) {
constraintSystem.addSubtypingConstraint(candidateWithFreshVariables.getReturnType(), expectedType);
constraintSystem.addSubtypingConstraint(EXPECTED_TYPE.assertSubtyping(candidateWithFreshVariables.getReturnType(), expectedType));
}
// Solution
@@ -2,7 +2,6 @@ package org.jetbrains.jet.lang.resolve.calls.inference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.Variance;
/**
@@ -11,7 +10,7 @@ import org.jetbrains.jet.lang.types.Variance;
public interface ConstraintSystem {
void registerTypeVariable(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull Variance positionVariance);
void addSubtypingConstraint(@NotNull JetType lower, @NotNull JetType upper);
void addSubtypingConstraint(@NotNull SubtypingConstraint constraint);
@NotNull
ConstraintSystemSolution solve();
@@ -382,9 +382,9 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
@Override
public void addSubtypingConstraint(@NotNull JetType lower, @NotNull JetType upper) {
TypeValue typeValueForLower = getTypeValueFor(lower);
TypeValue typeValueForUpper = getTypeValueFor(upper);
public void addSubtypingConstraint(@NotNull SubtypingConstraint constraint) {
TypeValue typeValueForLower = getTypeValueFor(constraint.getSubtype());
TypeValue typeValueForUpper = getTypeValueFor(constraint.getSupertype());
addSubtypingConstraintOnTypeValues(typeValueForLower, typeValueForUpper);
}
@@ -415,8 +415,16 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
}
// Lower bounds?
for (TypeValue lowerBound : typeValue.getLowerBounds()) {
if (lowerBound instanceof KnownType) {
KnownType knownBoundType = (KnownType) lowerBound;
boolean ok = constraintExpander.isSubtypeOf(knownBoundType.getType(), jetType);
if (!ok) {
listener.error("Error while expanding '" + knownBoundType.getType() + " :< " + jetType + "'");
return new Solution().registerError("Mismatch while expanding constraints");
}
}
}
}
// Fill in upper bounds from type parameter bounds
@@ -0,0 +1,35 @@
package org.jetbrains.jet.lang.resolve.calls.inference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.JetType;
import java.text.MessageFormat;
/**
* @author abreslav
*/
public enum ConstraintType implements Comparable<ConstraintType> {
// The order of these constants DOES matter
// they are compared according to ordinal() values
// First element has the highest priority
RECEIVER("{0} is not a subtype of the expected receiver type {1}"),
VALUE_ARGUMENT("Type mismatch: argument type is {0}, but {1} was expected"),
EXPECTED_TYPE("Resulting type is {0} but {1} was expected"),
PARAMETER_BOUND("Type parameter bound is not satisfied: {0} is not a subtype of {1}");
private final String errorMessageTemplate; // {0} is subtype, {1} is supertye
private ConstraintType(@NotNull String errorMessageTemplate) {
this.errorMessageTemplate = errorMessageTemplate;
}
@NotNull
public SubtypingConstraint assertSubtyping(@NotNull JetType subtype, @NotNull JetType supertype) {
return new SubtypingConstraint(this, subtype, supertype);
}
@NotNull
public String makeErrorMessage(@NotNull SubtypingConstraint constraint) {
return MessageFormat.format(errorMessageTemplate, constraint.getSubtype(), constraint.getSupertype());
}
}
@@ -0,0 +1,39 @@
package org.jetbrains.jet.lang.resolve.calls.inference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author abreslav
*/
public class SubtypingConstraint {
private final ConstraintType type;
private final JetType subtype;
private final JetType supertype;
public SubtypingConstraint(@NotNull ConstraintType type, @NotNull JetType subtype, @NotNull JetType supertype) {
this.type = type;
this.subtype = subtype;
this.supertype = supertype;
}
@NotNull
public JetType getSubtype() {
return subtype;
}
@NotNull
public JetType getSupertype() {
return supertype;
}
@NotNull
public ConstraintType getType() {
return type;
}
@NotNull
public String getErrorMessage() {
return type.makeErrorMessage(this);
}
}