From 8e10536ef93b8728315aa5a0e2e4f7de69347a75 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 9 Dec 2011 18:15:05 +0400 Subject: [PATCH] Constraint priorities introduced. Not used for the time being --- .../jet/lang/resolve/calls/CallResolver.java | 9 +++-- .../calls/inference/ConstraintSystem.java | 3 +- .../calls/inference/ConstraintSystemImpl.java | 18 ++++++--- .../calls/inference/ConstraintType.java | 35 +++++++++++++++++ .../calls/inference/SubtypingConstraint.java | 39 +++++++++++++++++++ 5 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintType.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/SubtypingConstraint.java diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index e611247ebe7..e8ed22f23a0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -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 diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java index 8511fb78b37..e071e19bef5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java @@ -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(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java index 8ea8f233b0c..931371e5f3e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java @@ -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 diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintType.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintType.java new file mode 100644 index 00000000000..d66578f1d83 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintType.java @@ -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 { + // 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()); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/SubtypingConstraint.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/SubtypingConstraint.java new file mode 100644 index 00000000000..5f62fb11233 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/SubtypingConstraint.java @@ -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); + } +}