added UNIT_EXPECTED_TYPE
use it for coercion to unit instead of repeating analysis twice
This commit is contained in:
@@ -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));
|
||||
|
||||
|
||||
+19
-36
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user