store constraint system without expected type constraint
for easier 'type inference expected type mismatch' reporting
This commit is contained in:
+1
-2
@@ -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;
|
||||
}
|
||||
|
||||
+3
-1
@@ -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();
|
||||
|
||||
+27
-12
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+8
-5
@@ -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) {
|
||||
|
||||
+2
-4
@@ -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);
|
||||
}
|
||||
|
||||
+15
-17
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user