report type mismatch deeply on branches for if

in type argument inference case
This commit is contained in:
Svetlana Isakova
2013-07-31 18:16:01 +04:00
parent c5b6ee4df3
commit e2f681c587
5 changed files with 107 additions and 27 deletions
@@ -21,7 +21,6 @@ import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory2;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingTrace;
@@ -223,7 +222,14 @@ public class TracingStrategyImpl implements TracingStrategy {
return;
}
if (constraintSystem.hasOnlyExpectedTypeMismatch()) {
reportTypeInferenceExpectedTypeMismatch(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH, reference, data, trace);
JetType declaredReturnType = data.descriptor.getReturnType();
if (declaredReturnType == null) return;
JetType substitutedReturnType = constraintSystem.getResultingSubstitutor().substitute(declaredReturnType, Variance.INVARIANT);
assert substitutedReturnType != null; //todo
assert !noExpectedType(data.expectedType) : "Expected type doesn't exist, but there is an expected type mismatch error";
trace.report(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.on(reference, data.expectedType, substitutedReturnType));
}
else if (constraintSystem.hasTypeConstructorMismatch()) {
trace.report(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH.on(reference, data));
@@ -237,20 +243,6 @@ public class TracingStrategyImpl implements TracingStrategy {
}
}
public static void reportTypeInferenceExpectedTypeMismatch(
@NotNull DiagnosticFactory2<JetExpression, JetType, JetType> diagnosticFactory,
@NotNull JetExpression reportOn, @NotNull InferenceErrorData.ExtendedInferenceErrorData data, @NotNull BindingTrace trace
) {
JetType declaredReturnType = data.descriptor.getReturnType();
if (declaredReturnType == null) return;
JetType substitutedReturnType = data.constraintSystem.getResultingSubstitutor().substitute(declaredReturnType, Variance.INVARIANT);
assert substitutedReturnType != null; //todo
assert !noExpectedType(data.expectedType) : "Expected type doesn't exist, but there is an expected type mismatch error";
trace.report(diagnosticFactory.on(reportOn, data.expectedType, substitutedReturnType));
}
@Override
public void upperBoundViolated(@NotNull BindingTrace trace, @NotNull InferenceErrorData inferenceErrorData) {
trace.report(Errors.TYPE_INFERENCE_UPPER_BOUND_VIOLATED.on(reference, inferenceErrorData));
@@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
@@ -37,21 +38,16 @@ 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.tasks.ResolutionCandidate;
import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy;
import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategyImpl;
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
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.JetTypeImpl;
import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.lang.types.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.jet.lang.diagnostics.Errors.TYPE_MISMATCH;
import static org.jetbrains.jet.lang.resolve.BindingContext.CALL;
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL;
@@ -216,6 +212,50 @@ public class ControlStructureTypingUtils {
}
/*package*/ static TracingStrategy createTracingForIf(final @NotNull Call callForIf) {
class CheckTypeContext {
public BindingTrace trace;
public JetType expectedType;
CheckTypeContext(@NotNull BindingTrace trace, @NotNull JetType expectedType) {
this.trace = trace;
this.expectedType = expectedType;
}
}
final JetVisitor<Void, CheckTypeContext> checkTypeVisitor = new JetVisitor<Void, CheckTypeContext>() {
private void checkExpressionType(@Nullable JetExpression expression, CheckTypeContext c) {
if (expression == null) return;
expression.accept(this, c);
}
@Override
public Void visitIfExpression(JetIfExpression ifExpression, CheckTypeContext c) {
checkExpressionType(ifExpression.getThen(), c);
checkExpressionType(ifExpression.getElse(), c);
return null;
}
@Override
public Void visitBlockExpression(JetBlockExpression expression, CheckTypeContext c) {
List<JetElement> statements = expression.getStatements();
if (!statements.isEmpty()) {
JetElement lastElement = statements.get(statements.size() - 1);
if (lastElement instanceof JetExpression) {
checkExpressionType((JetExpression) lastElement, c);
}
}
return null;
}
@Override
public Void visitExpression(JetExpression expression, CheckTypeContext c) {
JetTypeInfo typeInfo = BindingContextUtils.getRecordedTypeInfo(expression, c.trace.getBindingContext());
if (typeInfo != null) {
DataFlowUtils.checkType(typeInfo.getType(), expression, c.expectedType, typeInfo.getDataFlowInfo(), c.trace);
}
return null;
}
};
return new ThrowingOnErrorTracingStrategy("resolve 'if' as a call") {
@Override
@@ -245,9 +285,10 @@ public class ControlStructureTypingUtils {
return;
}
if (constraintSystem.hasOnlyExpectedTypeMismatch()) {
JetExpression ifExpression = callForIf.getCalleeExpression();
assert ifExpression != null;
TracingStrategyImpl.reportTypeInferenceExpectedTypeMismatch(TYPE_MISMATCH, ifExpression, data, trace);
JetExpression expression = callForIf.getCalleeExpression();
if (expression != null) {
expression.accept(checkTypeVisitor, new CheckTypeContext(trace, data.expectedType));
}
return;
}
super.typeInferenceFailed(trace, data);
@@ -151,7 +151,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
result = thenTypeInfo;
}
else {
result = JetTypeInfo.create(CommonSupertypes.commonSupertype(Arrays.asList(thenType, elseType)), thenDataFlowInfo.or(elseDataFlowInfo));
result = JetTypeInfo.create(TypeUtils.commonSupertypeForPossiblyNumberTypes(Arrays.asList(thenType, elseType)), thenDataFlowInfo.or(elseDataFlowInfo));
}
return DataFlowUtils.checkImplicitCast(result.getType(), ifExpression, contextWithExpectedType, isStatement, result.getDataFlowInfo());