diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java index 8548c135138..97aae00fe59 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java @@ -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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java index 041ee1e7b06..abc878a5ffd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java @@ -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 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; } 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 53de91d5d31..1f8a6ff8fda 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 @@ -104,7 +104,7 @@ public interface ConstraintSystem { /** * Returns true if there is type constructor mismatch only in {@link ConstraintPosition.EXPECTED_TYPE_POSITION}. */ - boolean hasExpectedTypeMismatch(); + boolean hasOnlyExpectedTypeMismatch(); /** * Returns true if there is an error in constraining types.

@@ -125,6 +125,8 @@ public interface ConstraintSystem { * - type constraints

* - variance of the type variable // 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 TypeSubstitutor getResultingSubstitutor(); 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 f97aec5d012..b9d0c5f751c 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 @@ -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; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/InferenceErrorData.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/InferenceErrorData.java index 2288cb90da4..bdc17232e74 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/InferenceErrorData.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/InferenceErrorData.java @@ -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 valueArgumentsTypes; private ExtendedInferenceErrorData( @NotNull CallableDescriptor descriptor, @NotNull ConstraintSystem constraintSystem, - @NotNull List valueArgumentsTypes, @Nullable JetType receiverArgumentType, @Nullable JetType expectedType + @NotNull List 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 valueArgumentsTypes, @Nullable JetType receiverArgumentType, @Nullable JetType expectedType) { - return new ExtendedInferenceErrorData(descriptor, constraintSystem, valueArgumentsTypes, receiverArgumentType, - expectedType != TypeUtils.NO_EXPECTED_TYPE ? expectedType : null); + @NotNull List 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) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategy.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategy.java index b05ba57a2e7..c8408c3446b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategy.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategy.java @@ -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); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategyImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategyImpl.java index eef28e3d959..b998b2b2362 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategyImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategyImpl.java @@ -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));