From 33ab7a3789124d3a3fef47d23da393c2c9c4482e Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Wed, 14 Aug 2013 12:34:00 +0400 Subject: [PATCH] added UNIT_EXPECTED_TYPE use it for coercion to unit instead of repeating analysis twice --- .../lang/resolve/calls/CandidateResolver.java | 9 ++- .../jetbrains/jet/lang/types/TypeUtils.java | 4 +- .../lang/types/expressions/DataFlowUtils.java | 3 +- .../expressions/ExpressionTypingServices.java | 55 +++++++------------ 4 files changed, 32 insertions(+), 39 deletions(-) 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 cd1b630c9d5..342c9000b14 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 @@ -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(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java index 1e6dc3de23b..f19d2cabc64 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java @@ -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 diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java index 2c0f07f8d28..d1dc8ead8cf 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java @@ -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)); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java index 8f74e5a4bd0..45da542e870 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java @@ -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); }