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.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
|
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.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.OverloadResolutionResults;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
|
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
|
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'
|
// Expected type mismatch was reported before as 'TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH'
|
||||||
ConstraintSystem constraintSystem = callToComplete.getConstraintSystem();
|
ConstraintSystem constraintSystem = callToComplete.getConstraintSystem();
|
||||||
if (constraintSystem != null && constraintSystem.hasExpectedTypeMismatch()) return null;
|
if (constraintSystem != null && constraintSystem.hasOnlyExpectedTypeMismatch()) return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return results.isSingleResult() ? results.getResultingCall() : null;
|
return results.isSingleResult() ? results.getResultingCall() : null;
|
||||||
|
|||||||
@@ -225,13 +225,10 @@ public class CandidateResolver {
|
|||||||
ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
|
ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
|
||||||
assert constraintSystem != null;
|
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()) {
|
if (!constraintSystem.isSuccessful()) {
|
||||||
resolvedCall.setResultingSubstitutor(constraintSystemWithoutExpectedTypeConstraint.getResultingSubstitutor());
|
resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
|
||||||
completeNestedCallsInference(context);
|
completeNestedCallsInference(context);
|
||||||
List<JetType> argumentTypes = checkValueArgumentTypes(context, resolvedCall, context.trace,
|
List<JetType> argumentTypes = checkValueArgumentTypes(context, resolvedCall, context.trace,
|
||||||
RESOLVE_FUNCTION_ARGUMENTS).argumentTypes;
|
RESOLVE_FUNCTION_ARGUMENTS).argumentTypes;
|
||||||
@@ -239,7 +236,7 @@ public class CandidateResolver {
|
|||||||
InferenceErrorData.ExtendedInferenceErrorData errorData = InferenceErrorData
|
InferenceErrorData.ExtendedInferenceErrorData errorData = InferenceErrorData
|
||||||
.create(descriptor, constraintSystem, argumentTypes, receiverType, context.expectedType);
|
.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);
|
resolvedCall.addStatus(ResolutionStatus.OTHER_ERROR);
|
||||||
return;
|
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}.
|
* 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/>
|
* Returns <tt>true</tt> if there is an error in constraining types. <p/>
|
||||||
@@ -125,6 +125,8 @@ public interface ConstraintSystem {
|
|||||||
* - type constraints <p/>
|
* - type constraints <p/>
|
||||||
* - variance of the type variable // not implemented yet <p/>
|
* - variance of the type variable // not implemented yet <p/>
|
||||||
* - type parameter bounds (that can bind type variables with each other). // not implemented yet
|
* - 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
|
@NotNull
|
||||||
TypeSubstitutor getResultingSubstitutor();
|
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.checker.TypingConstraints;
|
||||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -53,7 +52,9 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
private final TypeSubstitutor resultingSubstitutor;
|
private final TypeSubstitutor resultingSubstitutor;
|
||||||
private final TypeSubstitutor currentSubstitutor;
|
private final TypeSubstitutor currentSubstitutor;
|
||||||
private boolean hasErrorInConstrainingTypes;
|
private boolean hasErrorInConstrainingTypes;
|
||||||
private boolean hasExpectedTypeMismatch;
|
|
||||||
|
@Nullable
|
||||||
|
private ConstraintSystem systemWithoutExpectedTypeConstraint;
|
||||||
|
|
||||||
public ConstraintSystemImpl() {
|
public ConstraintSystemImpl() {
|
||||||
this.resultingSubstitutor = createTypeSubstitutorWithDefaultForUnknownTypeParameter(new TypeProjection(CANT_INFER_TYPE_PARAMETER));
|
this.resultingSubstitutor = createTypeSubstitutorWithDefaultForUnknownTypeParameter(new TypeProjection(CANT_INFER_TYPE_PARAMETER));
|
||||||
@@ -102,13 +103,20 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasExpectedTypeMismatch() {
|
public boolean hasOnlyExpectedTypeMismatch() {
|
||||||
return hasExpectedTypeMismatch
|
if (systemWithoutExpectedTypeConstraint == null) {
|
||||||
|| (errorConstraintPositions.size() == 1 && errorConstraintPositions.contains(ConstraintPosition.EXPECTED_TYPE_POSITION));
|
// the expected type constraint isn't added, there can't be an error with it
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
public void setHasExpectedTypeMismatch() {
|
if (!isSuccessful() && systemWithoutExpectedTypeConstraint.isSuccessful()) {
|
||||||
hasExpectedTypeMismatch = true;
|
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
|
@Override
|
||||||
@@ -157,6 +165,11 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
@NotNull JetType subjectType,
|
@NotNull JetType subjectType,
|
||||||
@NotNull ConstraintPosition constraintPosition
|
@NotNull ConstraintPosition constraintPosition
|
||||||
) {
|
) {
|
||||||
|
if (constrainingType == TypeUtils.NO_EXPECTED_TYPE) return;
|
||||||
|
|
||||||
|
if (constraintPosition == ConstraintPosition.EXPECTED_TYPE_POSITION) {
|
||||||
|
systemWithoutExpectedTypeConstraint = copy();
|
||||||
|
}
|
||||||
addConstraint(SUB_TYPE, subjectType, constrainingType, constraintPosition);
|
addConstraint(SUB_TYPE, subjectType, constrainingType, constraintPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,9 +225,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isErrorOrSpecialType(@Nullable JetType type) {
|
private boolean isErrorOrSpecialType(@Nullable JetType type) {
|
||||||
if (type == TypeUtils.NO_EXPECTED_TYPE
|
if (type == DONT_CARE || type == CANT_INFER_TYPE_PARAMETER) {
|
||||||
|| type == DONT_CARE
|
|
||||||
|| type == CANT_INFER_TYPE_PARAMETER) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,6 +376,10 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public TypeSubstitutor getResultingSubstitutor() {
|
public TypeSubstitutor getResultingSubstitutor() {
|
||||||
|
if (hasOnlyExpectedTypeMismatch()) {
|
||||||
|
assert systemWithoutExpectedTypeConstraint != null;
|
||||||
|
return systemWithoutExpectedTypeConstraint.getResultingSubstitutor();
|
||||||
|
}
|
||||||
return resultingSubstitutor;
|
return resultingSubstitutor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-5
@@ -25,7 +25,9 @@ import org.jetbrains.jet.lang.types.TypeUtils;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class InferenceErrorData {
|
public class InferenceErrorData {
|
||||||
|
@NotNull
|
||||||
public final CallableDescriptor descriptor;
|
public final CallableDescriptor descriptor;
|
||||||
|
@NotNull
|
||||||
public final ConstraintSystem constraintSystem;
|
public final ConstraintSystem constraintSystem;
|
||||||
|
|
||||||
private InferenceErrorData(@NotNull CallableDescriptor descriptor, @NotNull ConstraintSystem constraintSystem) {
|
private InferenceErrorData(@NotNull CallableDescriptor descriptor, @NotNull ConstraintSystem constraintSystem) {
|
||||||
@@ -34,14 +36,16 @@ public class InferenceErrorData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class ExtendedInferenceErrorData extends InferenceErrorData {
|
public static class ExtendedInferenceErrorData extends InferenceErrorData {
|
||||||
|
@Nullable
|
||||||
public final JetType receiverArgumentType;
|
public final JetType receiverArgumentType;
|
||||||
|
@NotNull
|
||||||
public final JetType expectedType;
|
public final JetType expectedType;
|
||||||
|
@NotNull
|
||||||
public final List<JetType> valueArgumentsTypes;
|
public final List<JetType> valueArgumentsTypes;
|
||||||
|
|
||||||
private ExtendedInferenceErrorData(
|
private ExtendedInferenceErrorData(
|
||||||
@NotNull CallableDescriptor descriptor, @NotNull ConstraintSystem constraintSystem,
|
@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);
|
super(descriptor, constraintSystem);
|
||||||
this.receiverArgumentType = receiverArgumentType;
|
this.receiverArgumentType = receiverArgumentType;
|
||||||
@@ -51,9 +55,8 @@ public class InferenceErrorData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static ExtendedInferenceErrorData create(@NotNull CallableDescriptor descriptor, @NotNull ConstraintSystem constraintSystem,
|
public static ExtendedInferenceErrorData create(@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) {
|
||||||
return new ExtendedInferenceErrorData(descriptor, constraintSystem, valueArgumentsTypes, receiverArgumentType,
|
return new ExtendedInferenceErrorData(descriptor, constraintSystem, valueArgumentsTypes, receiverArgumentType, expectedType);
|
||||||
expectedType != TypeUtils.NO_EXPECTED_TYPE ? expectedType : null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static InferenceErrorData create(@NotNull CallableDescriptor descriptor, @NotNull ConstraintSystem constraintSystem) {
|
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) {}
|
public void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptorWithVisibility descriptor) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull ExtendedInferenceErrorData inferenceErrorData,
|
public void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull ExtendedInferenceErrorData inferenceErrorData) {}
|
||||||
@NotNull ConstraintSystem systemWithoutExpectedTypeConstraint) {}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void upperBoundViolated(@NotNull BindingTrace trace, @NotNull InferenceErrorData inferenceErrorData) {}
|
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 invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptorWithVisibility descriptor);
|
||||||
|
|
||||||
void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull ExtendedInferenceErrorData inferenceErrorData,
|
void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull ExtendedInferenceErrorData inferenceErrorData);
|
||||||
@NotNull ConstraintSystem systemWithoutExpectedTypeConstraint);
|
|
||||||
|
|
||||||
void upperBoundViolated(@NotNull BindingTrace trace, @NotNull InferenceErrorData 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.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
|
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.inference.InferenceErrorData;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
|
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.resolve.scopes.receivers.ReceiverValue;
|
||||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
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.Variance;
|
||||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
||||||
import org.jetbrains.jet.lexer.JetToken;
|
import org.jetbrains.jet.lexer.JetToken;
|
||||||
@@ -206,26 +206,24 @@ public class TracingStrategyImpl implements TracingStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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;
|
ConstraintSystem constraintSystem = data.constraintSystem;
|
||||||
assert !constraintSystem.isSuccessful();
|
assert !constraintSystem.isSuccessful() : "Report error only for not successful constraint system";
|
||||||
|
|
||||||
if (constraintSystem.hasErrorInConstrainingTypes()) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
boolean successfulWithoutExpectedTypeConstraint = systemWithoutExpectedTypeConstraint.isSuccessful();
|
if (constraintSystem.hasOnlyExpectedTypeMismatch()) {
|
||||||
if (constraintSystem.hasExpectedTypeMismatch() || successfulWithoutExpectedTypeConstraint) {
|
JetType declaredReturnType = data.descriptor.getReturnType();
|
||||||
JetType returnType = data.descriptor.getReturnType();
|
if (declaredReturnType == null) return;
|
||||||
assert returnType != null;
|
|
||||||
if (successfulWithoutExpectedTypeConstraint) {
|
JetType substitutedReturnType = constraintSystem.getResultingSubstitutor().substitute(declaredReturnType, Variance.INVARIANT);
|
||||||
returnType = systemWithoutExpectedTypeConstraint.getResultingSubstitutor().substitute(returnType, Variance.INVARIANT);
|
assert substitutedReturnType != null; //todo
|
||||||
assert returnType != null;
|
|
||||||
}
|
assert data.expectedType != TypeUtils.NO_EXPECTED_TYPE : "Expected type doesn't exist, but there is an expected type mismatch error";
|
||||||
assert data.expectedType != null;
|
trace.report(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.on(reference, substitutedReturnType, data.expectedType));
|
||||||
trace.report(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.on(reference, returnType, data.expectedType));
|
|
||||||
//todo[ConstraintSystemImpl]
|
|
||||||
if (constraintSystem instanceof ConstraintSystemImpl) {
|
|
||||||
((ConstraintSystemImpl) constraintSystem).setHasExpectedTypeMismatch();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (constraintSystem.hasTypeConstructorMismatch()) {
|
else if (constraintSystem.hasTypeConstructorMismatch()) {
|
||||||
trace.report(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH.on(reference, data));
|
trace.report(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH.on(reference, data));
|
||||||
|
|||||||
Reference in New Issue
Block a user