store constraint system without expected type constraint

for easier 'type inference expected type mismatch' reporting
This commit is contained in:
Svetlana Isakova
2013-03-06 15:55:48 +04:00
parent 54cd8c82a3
commit 4d4fd5885d
7 changed files with 59 additions and 47 deletions
@@ -30,7 +30,6 @@ import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
@@ -166,7 +165,7 @@ public class CallExpressionResolver {
// Expected type mismatch was reported before as 'TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH'
ConstraintSystem constraintSystem = callToComplete.getConstraintSystem();
if (constraintSystem != null && constraintSystem.hasExpectedTypeMismatch()) return null;
if (constraintSystem != null && constraintSystem.hasOnlyExpectedTypeMismatch()) return null;
}
return results.isSingleResult() ? results.getResultingCall() : null;
@@ -225,13 +225,10 @@ public class CandidateResolver {
ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
assert constraintSystem != null;
ConstraintSystem constraintSystemWithoutExpectedTypeConstraint = constraintSystem.copy();
constraintSystem.addSupertypeConstraint(context.expectedType, descriptor.getReturnType(),
ConstraintPosition.EXPECTED_TYPE_POSITION);
constraintSystem.addSupertypeConstraint(context.expectedType, descriptor.getReturnType(), ConstraintPosition.EXPECTED_TYPE_POSITION);
if (!constraintSystem.isSuccessful()) {
resolvedCall.setResultingSubstitutor(constraintSystemWithoutExpectedTypeConstraint.getResultingSubstitutor());
resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
completeNestedCallsInference(context);
List<JetType> argumentTypes = checkValueArgumentTypes(context, resolvedCall, context.trace,
RESOLVE_FUNCTION_ARGUMENTS).argumentTypes;
@@ -239,7 +236,7 @@ public class CandidateResolver {
InferenceErrorData.ExtendedInferenceErrorData errorData = InferenceErrorData
.create(descriptor, constraintSystem, argumentTypes, receiverType, context.expectedType);
context.tracing.typeInferenceFailed(context.trace, errorData, constraintSystemWithoutExpectedTypeConstraint);
context.tracing.typeInferenceFailed(context.trace, errorData);
resolvedCall.addStatus(ResolutionStatus.OTHER_ERROR);
return;
}
@@ -104,7 +104,7 @@ public interface ConstraintSystem {
/**
* Returns <tt>true</tt> if there is type constructor mismatch only in {@link ConstraintPosition.EXPECTED_TYPE_POSITION}.
*/
boolean hasExpectedTypeMismatch();
boolean hasOnlyExpectedTypeMismatch();
/**
* Returns <tt>true</tt> if there is an error in constraining types. <p/>
@@ -125,6 +125,8 @@ public interface ConstraintSystem {
* - type constraints <p/>
* - variance of the type variable // not implemented yet <p/>
* - type parameter bounds (that can bind type variables with each other). // not implemented yet
* If the addition of the 'expected type' constraint made the system fail,
* this constraint is not included in the resulting substitution.
*/
@NotNull
TypeSubstitutor getResultingSubstitutor();
@@ -31,7 +31,6 @@ import org.jetbrains.jet.lang.types.checker.TypeCheckingProcedure;
import org.jetbrains.jet.lang.types.checker.TypingConstraints;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -53,7 +52,9 @@ public class ConstraintSystemImpl implements ConstraintSystem {
private final TypeSubstitutor resultingSubstitutor;
private final TypeSubstitutor currentSubstitutor;
private boolean hasErrorInConstrainingTypes;
private boolean hasExpectedTypeMismatch;
@Nullable
private ConstraintSystem systemWithoutExpectedTypeConstraint;
public ConstraintSystemImpl() {
this.resultingSubstitutor = createTypeSubstitutorWithDefaultForUnknownTypeParameter(new TypeProjection(CANT_INFER_TYPE_PARAMETER));
@@ -102,13 +103,20 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
@Override
public boolean hasExpectedTypeMismatch() {
return hasExpectedTypeMismatch
|| (errorConstraintPositions.size() == 1 && errorConstraintPositions.contains(ConstraintPosition.EXPECTED_TYPE_POSITION));
}
public void setHasExpectedTypeMismatch() {
hasExpectedTypeMismatch = true;
public boolean hasOnlyExpectedTypeMismatch() {
if (systemWithoutExpectedTypeConstraint == null) {
// the expected type constraint isn't added, there can't be an error with it
return false;
}
if (!isSuccessful() && systemWithoutExpectedTypeConstraint.isSuccessful()) {
return true;
}
if (errorConstraintPositions.size() == 1 && errorConstraintPositions.contains(ConstraintPosition.EXPECTED_TYPE_POSITION)) {
// if systemWithoutExpectedTypeConstraint has unknown type parameters, it's not successful,
// but there can be expected type mismatch after expected type is added
return true;
}
return false;
}
@Override
@@ -157,6 +165,11 @@ public class ConstraintSystemImpl implements ConstraintSystem {
@NotNull JetType subjectType,
@NotNull ConstraintPosition constraintPosition
) {
if (constrainingType == TypeUtils.NO_EXPECTED_TYPE) return;
if (constraintPosition == ConstraintPosition.EXPECTED_TYPE_POSITION) {
systemWithoutExpectedTypeConstraint = copy();
}
addConstraint(SUB_TYPE, subjectType, constrainingType, constraintPosition);
}
@@ -212,9 +225,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
private boolean isErrorOrSpecialType(@Nullable JetType type) {
if (type == TypeUtils.NO_EXPECTED_TYPE
|| type == DONT_CARE
|| type == CANT_INFER_TYPE_PARAMETER) {
if (type == DONT_CARE || type == CANT_INFER_TYPE_PARAMETER) {
return true;
}
@@ -365,6 +376,10 @@ public class ConstraintSystemImpl implements ConstraintSystem {
@NotNull
@Override
public TypeSubstitutor getResultingSubstitutor() {
if (hasOnlyExpectedTypeMismatch()) {
assert systemWithoutExpectedTypeConstraint != null;
return systemWithoutExpectedTypeConstraint.getResultingSubstitutor();
}
return resultingSubstitutor;
}
@@ -25,7 +25,9 @@ import org.jetbrains.jet.lang.types.TypeUtils;
import java.util.List;
public class InferenceErrorData {
@NotNull
public final CallableDescriptor descriptor;
@NotNull
public final ConstraintSystem constraintSystem;
private InferenceErrorData(@NotNull CallableDescriptor descriptor, @NotNull ConstraintSystem constraintSystem) {
@@ -34,14 +36,16 @@ public class InferenceErrorData {
}
public static class ExtendedInferenceErrorData extends InferenceErrorData {
@Nullable
public final JetType receiverArgumentType;
@NotNull
public final JetType expectedType;
@NotNull
public final List<JetType> valueArgumentsTypes;
private ExtendedInferenceErrorData(
@NotNull CallableDescriptor descriptor, @NotNull ConstraintSystem constraintSystem,
@NotNull List<JetType> valueArgumentsTypes, @Nullable JetType receiverArgumentType, @Nullable JetType expectedType
@NotNull List<JetType> valueArgumentsTypes, @Nullable JetType receiverArgumentType, @NotNull JetType expectedType
) {
super(descriptor, constraintSystem);
this.receiverArgumentType = receiverArgumentType;
@@ -51,9 +55,8 @@ public class InferenceErrorData {
}
public static ExtendedInferenceErrorData create(@NotNull CallableDescriptor descriptor, @NotNull ConstraintSystem constraintSystem,
@NotNull List<JetType> valueArgumentsTypes, @Nullable JetType receiverArgumentType, @Nullable JetType expectedType) {
return new ExtendedInferenceErrorData(descriptor, constraintSystem, valueArgumentsTypes, receiverArgumentType,
expectedType != TypeUtils.NO_EXPECTED_TYPE ? expectedType : null);
@NotNull List<JetType> valueArgumentsTypes, @Nullable JetType receiverArgumentType, @NotNull JetType expectedType) {
return new ExtendedInferenceErrorData(descriptor, constraintSystem, valueArgumentsTypes, receiverArgumentType, expectedType);
}
public static InferenceErrorData create(@NotNull CallableDescriptor descriptor, @NotNull ConstraintSystem constraintSystem) {
@@ -92,8 +92,7 @@ public interface TracingStrategy {
public void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptorWithVisibility descriptor) {}
@Override
public void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull ExtendedInferenceErrorData inferenceErrorData,
@NotNull ConstraintSystem systemWithoutExpectedTypeConstraint) {}
public void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull ExtendedInferenceErrorData inferenceErrorData) {}
@Override
public void upperBoundViolated(@NotNull BindingTrace trace, @NotNull InferenceErrorData inferenceErrorData) {}
@@ -136,8 +135,7 @@ public interface TracingStrategy {
void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptorWithVisibility descriptor);
void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull ExtendedInferenceErrorData inferenceErrorData,
@NotNull ConstraintSystem systemWithoutExpectedTypeConstraint);
void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull ExtendedInferenceErrorData inferenceErrorData);
void upperBoundViolated(@NotNull BindingTrace trace, @NotNull InferenceErrorData inferenceErrorData);
}
@@ -25,7 +25,6 @@ import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
import org.jetbrains.jet.lang.resolve.calls.inference.InferenceErrorData;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
@@ -34,6 +33,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.jet.lexer.JetToken;
@@ -206,26 +206,24 @@ public class TracingStrategyImpl implements TracingStrategy {
}
@Override
public void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull InferenceErrorData.ExtendedInferenceErrorData data, @NotNull ConstraintSystem systemWithoutExpectedTypeConstraint) {
public void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull InferenceErrorData.ExtendedInferenceErrorData data) {
ConstraintSystem constraintSystem = data.constraintSystem;
assert !constraintSystem.isSuccessful();
assert !constraintSystem.isSuccessful() : "Report error only for not successful constraint system";
if (constraintSystem.hasErrorInConstrainingTypes()) {
// Do not report type inference errors if there is one in the arguments
// (it's useful, when the arguments, e.g. lambdas or calls are incomplete)
return;
}
boolean successfulWithoutExpectedTypeConstraint = systemWithoutExpectedTypeConstraint.isSuccessful();
if (constraintSystem.hasExpectedTypeMismatch() || successfulWithoutExpectedTypeConstraint) {
JetType returnType = data.descriptor.getReturnType();
assert returnType != null;
if (successfulWithoutExpectedTypeConstraint) {
returnType = systemWithoutExpectedTypeConstraint.getResultingSubstitutor().substitute(returnType, Variance.INVARIANT);
assert returnType != null;
}
assert data.expectedType != null;
trace.report(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.on(reference, returnType, data.expectedType));
//todo[ConstraintSystemImpl]
if (constraintSystem instanceof ConstraintSystemImpl) {
((ConstraintSystemImpl) constraintSystem).setHasExpectedTypeMismatch();
}
if (constraintSystem.hasOnlyExpectedTypeMismatch()) {
JetType declaredReturnType = data.descriptor.getReturnType();
if (declaredReturnType == null) return;
JetType substitutedReturnType = constraintSystem.getResultingSubstitutor().substitute(declaredReturnType, Variance.INVARIANT);
assert substitutedReturnType != null; //todo
assert data.expectedType != TypeUtils.NO_EXPECTED_TYPE : "Expected type doesn't exist, but there is an expected type mismatch error";
trace.report(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.on(reference, substitutedReturnType, data.expectedType));
}
else if (constraintSystem.hasTypeConstructorMismatch()) {
trace.report(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH.on(reference, data));