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()) {
|
if (constraintSystem.hasContradiction()) {
|
||||||
return reportInferenceError(context);
|
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);
|
boolean boundsAreSatisfied = ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, /*substituteOtherTypeParametersInBounds=*/true);
|
||||||
if (!boundsAreSatisfied || constraintSystem.hasUnknownParameters()) {
|
if (!boundsAreSatisfied || constraintSystem.hasUnknownParameters()) {
|
||||||
ConstraintSystemImpl copy = (ConstraintSystemImpl) constraintSystem.copy();
|
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 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) {
|
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
|
@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.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.AUTOCAST;
|
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;
|
import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
|
||||||
|
|
||||||
public class DataFlowUtils {
|
public class DataFlowUtils {
|
||||||
@@ -193,7 +194,7 @@ public class DataFlowUtils {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static JetType checkImplicitCast(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ExpressionTypingContext context, boolean isStatement) {
|
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))) {
|
(KotlinBuiltIns.getInstance().isUnit(expressionType) || KotlinBuiltIns.getInstance().isAny(expressionType))) {
|
||||||
context.trace.report(IMPLICIT_CAST_TO_UNIT_OR_ANY.on(expression, 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.CallExpressionResolver;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
|
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
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.ExpressionPosition;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext;
|
import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
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.resolve.BindingContext.STATEMENT;
|
||||||
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
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.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 {
|
public class ExpressionTypingServices {
|
||||||
|
|
||||||
@@ -256,41 +258,10 @@ public class ExpressionTypingServices {
|
|||||||
}
|
}
|
||||||
trace.record(STATEMENT, statement);
|
trace.record(STATEMENT, statement);
|
||||||
JetExpression statementExpression = (JetExpression) statement;
|
JetExpression statementExpression = (JetExpression) statement;
|
||||||
//TODO constructor assert context.expectedType != FORBIDDEN : ""
|
|
||||||
if (!iterator.hasNext()) {
|
if (!iterator.hasNext()) {
|
||||||
if (!noExpectedType(context.expectedType)) {
|
if (noExpectedType(context.expectedType) && context.expectedType != UNIT_EXPECTED_TYPE) {
|
||||||
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 {
|
|
||||||
result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true);
|
result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true);
|
||||||
if (coercionStrategyForLastExpression == CoercionStrategy.COERCION_TO_UNIT) {
|
if (coercionStrategyForLastExpression == COERCION_TO_UNIT) {
|
||||||
boolean mightBeUnit = false;
|
boolean mightBeUnit = false;
|
||||||
if (statementExpression instanceof JetDeclaration) {
|
if (statementExpression instanceof JetDeclaration) {
|
||||||
mightBeUnit = true;
|
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 {
|
else {
|
||||||
result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true);
|
result = blockLevelVisitor.getTypeInfo(statementExpression, newContext.replaceContextDependency(ContextDependency.INDEPENDENT), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
DataFlowInfo newDataFlowInfo = result.getDataFlowInfo();
|
DataFlowInfo newDataFlowInfo = result.getDataFlowInfo();
|
||||||
if (newDataFlowInfo != context.dataFlowInfo) {
|
if (newDataFlowInfo != context.dataFlowInfo) {
|
||||||
newContext = createContext(newContext, trace, scope, newDataFlowInfo, NO_EXPECTED_TYPE);
|
newContext = newContext.replaceDataFlowInfo(newDataFlowInfo);
|
||||||
}
|
}
|
||||||
blockLevelVisitor = ExpressionTypingVisitorDispatcher.createForBlock(scope);
|
blockLevelVisitor = ExpressionTypingVisitorDispatcher.createForBlock(scope);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user