added UNIT_EXPECTED_TYPE

use it for coercion to unit instead of repeating analysis twice
This commit is contained in:
Svetlana Isakova
2013-08-14 12:34:00 +04:00
parent 756cb3759b
commit 33ab7a3789
4 changed files with 32 additions and 39 deletions
@@ -256,7 +256,14 @@ public class CandidateResolver {
if (constraintSystem.hasContradiction()) {
return reportInferenceError(context);
}
if (!constraintSystem.isSuccessful() && context.expectedType == TypeUtils.UNIT_EXPECTED_TYPE) {
ConstraintSystemImpl copy = (ConstraintSystemImpl) constraintSystem.copy();
copy.addSupertypeConstraint(KotlinBuiltIns.getInstance().getUnitType(), descriptor.getReturnType(), ConstraintPosition.EXPECTED_TYPE_POSITION);
if (copy.isSuccessful()) {
constraintSystem = copy;
resolvedCall.setConstraintSystem(constraintSystem);
}
}
boolean boundsAreSatisfied = ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, /*substituteOtherTypeParametersInBounds=*/true);
if (!boundsAreSatisfied || constraintSystem.hasUnknownParameters()) {
ConstraintSystemImpl copy = (ConstraintSystemImpl) constraintSystem.copy();
@@ -85,8 +85,10 @@ public class TypeUtils {
public static final JetType UNKNOWN_EXPECTED_TYPE = new SpecialType("UNKNOWN_EXPECTED_TYPE");
public static final JetType UNIT_EXPECTED_TYPE = new SpecialType("UNIT_EXPECTED_TYPE");
public static boolean noExpectedType(@NotNull JetType type) {
return type == NO_EXPECTED_TYPE || type == UNKNOWN_EXPECTED_TYPE;
return type == NO_EXPECTED_TYPE || type == UNKNOWN_EXPECTED_TYPE || type == UNIT_EXPECTED_TYPE;
}
@NotNull
@@ -38,6 +38,7 @@ import org.jetbrains.jet.lexer.JetTokens;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.AUTOCAST;
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
public class DataFlowUtils {
@@ -193,7 +194,7 @@ public class DataFlowUtils {
@Nullable
public static JetType checkImplicitCast(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ExpressionTypingContext context, boolean isStatement) {
if (expressionType != null && noExpectedType(context.expectedType) && !isStatement &&
if (expressionType != null && context.expectedType == NO_EXPECTED_TYPE && !isStatement &&
(KotlinBuiltIns.getInstance().isUnit(expressionType) || KotlinBuiltIns.getInstance().isAny(expressionType))) {
context.trace.report(IMPLICIT_CAST_TO_UNIT_OR_ANY.on(expression, expressionType));
@@ -30,6 +30,7 @@ import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver;
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.context.ContextDependency;
import org.jetbrains.jet.lang.resolve.calls.context.ExpressionPosition;
import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
@@ -47,8 +48,9 @@ import java.util.List;
import static org.jetbrains.jet.lang.resolve.BindingContext.STATEMENT;
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
import static org.jetbrains.jet.lang.types.TypeUtils.UNIT_EXPECTED_TYPE;
import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.makeTraceInterceptingTypeMismatch;
import static org.jetbrains.jet.lang.types.expressions.CoercionStrategy.COERCION_TO_UNIT;
public class ExpressionTypingServices {
@@ -256,41 +258,10 @@ public class ExpressionTypingServices {
}
trace.record(STATEMENT, statement);
JetExpression statementExpression = (JetExpression) statement;
//TODO constructor assert context.expectedType != FORBIDDEN : ""
if (!iterator.hasNext()) {
if (!noExpectedType(context.expectedType)) {
if (coercionStrategyForLastExpression == CoercionStrategy.COERCION_TO_UNIT && KotlinBuiltIns.getInstance().isUnit(context.expectedType)) {
// This implements coercion to Unit
TemporaryBindingTrace temporaryTraceExpectingUnit = TemporaryBindingTrace.create(trace, "trace to resolve coercion to unit with expected type");
boolean[] mismatch = new boolean[1];
ObservableBindingTrace errorInterceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceExpectingUnit, statementExpression, mismatch);
newContext = createContext(newContext, errorInterceptingTrace, scope, newContext.dataFlowInfo, context.expectedType);
result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true);
if (mismatch[0]) {
TemporaryBindingTrace temporaryTraceNoExpectedType = TemporaryBindingTrace.create(trace, "trace to resolve coercion to unit without expected type");
mismatch[0] = false;
ObservableBindingTrace interceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceNoExpectedType, statementExpression, mismatch);
newContext = createContext(newContext, interceptingTrace, scope, newContext.dataFlowInfo, NO_EXPECTED_TYPE);
result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true);
if (mismatch[0]) {
temporaryTraceExpectingUnit.commit();
}
else {
temporaryTraceNoExpectedType.commit();
}
}
else {
temporaryTraceExpectingUnit.commit();
}
}
else {
newContext = createContext(newContext, trace, scope, newContext.dataFlowInfo, context.expectedType);
result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true);
}
}
else {
if (noExpectedType(context.expectedType) && context.expectedType != UNIT_EXPECTED_TYPE) {
result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true);
if (coercionStrategyForLastExpression == CoercionStrategy.COERCION_TO_UNIT) {
if (coercionStrategyForLastExpression == COERCION_TO_UNIT) {
boolean mightBeUnit = false;
if (statementExpression instanceof JetDeclaration) {
mightBeUnit = true;
@@ -310,14 +281,26 @@ public class ExpressionTypingServices {
}
}
}
else {
JetType expectedType;
if (context.expectedType == UNIT_EXPECTED_TYPE || (coercionStrategyForLastExpression == COERCION_TO_UNIT
&& KotlinBuiltIns.getInstance().isUnit(context.expectedType))) {
expectedType = UNIT_EXPECTED_TYPE;
}
else {
expectedType = context.expectedType;
}
result = blockLevelVisitor.getTypeInfo(statementExpression, newContext.replaceExpectedType(expectedType), true);
}
}
else {
result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true);
result = blockLevelVisitor.getTypeInfo(statementExpression, newContext.replaceContextDependency(ContextDependency.INDEPENDENT), true);
}
DataFlowInfo newDataFlowInfo = result.getDataFlowInfo();
if (newDataFlowInfo != context.dataFlowInfo) {
newContext = createContext(newContext, trace, scope, newDataFlowInfo, NO_EXPECTED_TYPE);
newContext = newContext.replaceDataFlowInfo(newDataFlowInfo);
}
blockLevelVisitor = ExpressionTypingVisitorDispatcher.createForBlock(scope);
}