KT-351 Distinguish statement and expression positions
This commit is contained in:
@@ -232,6 +232,14 @@ public interface Errors {
|
|||||||
ParameterizedDiagnosticFactory1<JetType> RETURN_TYPE_MISMATCH = ParameterizedDiagnosticFactory1.create(ERROR, "This function must return a value of type {0}");
|
ParameterizedDiagnosticFactory1<JetType> RETURN_TYPE_MISMATCH = ParameterizedDiagnosticFactory1.create(ERROR, "This function must return a value of type {0}");
|
||||||
ParameterizedDiagnosticFactory1<JetType> EXPECTED_TYPE_MISMATCH = ParameterizedDiagnosticFactory1.create(ERROR, "Expected a value of type {0}");
|
ParameterizedDiagnosticFactory1<JetType> EXPECTED_TYPE_MISMATCH = ParameterizedDiagnosticFactory1.create(ERROR, "Expected a value of type {0}");
|
||||||
ParameterizedDiagnosticFactory1<JetType> ASSIGNMENT_TYPE_MISMATCH = ParameterizedDiagnosticFactory1.create(ERROR, "Expected a value of type {0}. Assignment operation is not an expression, so it does not return any value");
|
ParameterizedDiagnosticFactory1<JetType> ASSIGNMENT_TYPE_MISMATCH = ParameterizedDiagnosticFactory1.create(ERROR, "Expected a value of type {0}. Assignment operation is not an expression, so it does not return any value");
|
||||||
|
ParameterizedDiagnosticFactory1<JetType> IMPLICIT_CAST_TO_UNIT_OR_ANY = ParameterizedDiagnosticFactory1.create(WARNING, "Type was casted to ''{0}''. Please specify ''{0}'' as expected type, if you mean such cast");
|
||||||
|
ParameterizedDiagnosticFactory1<JetExpression> EXPRESSION_EXPECTED = new ParameterizedDiagnosticFactory1<JetExpression>(ERROR, "{0} is not an expression, and only expression are allowed here") {
|
||||||
|
@Override
|
||||||
|
protected String makeMessageFor(JetExpression expression) {
|
||||||
|
String expressionType = expression.toString();
|
||||||
|
return expressionType.substring(0, 1) + expressionType.substring(1).toLowerCase();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ParameterizedDiagnosticFactory1<JetType> UPPER_BOUND_VIOLATED = ParameterizedDiagnosticFactory1.create(ERROR, "An upper bound {0} is violated"); // TODO : Message
|
ParameterizedDiagnosticFactory1<JetType> UPPER_BOUND_VIOLATED = ParameterizedDiagnosticFactory1.create(ERROR, "An upper bound {0} is violated"); // TODO : Message
|
||||||
ParameterizedDiagnosticFactory1<JetType> FINAL_CLASS_OBJECT_UPPER_BOUND = ParameterizedDiagnosticFactory1.create(ERROR, "{0} is a final type, and thus a class object cannot extend it");
|
ParameterizedDiagnosticFactory1<JetType> FINAL_CLASS_OBJECT_UPPER_BOUND = ParameterizedDiagnosticFactory1.create(ERROR, "{0} is a final type, and thus a class object cannot extend it");
|
||||||
|
|||||||
@@ -242,6 +242,11 @@ public class JetStandardClasses {
|
|||||||
public static JetType getAnyType() {
|
public static JetType getAnyType() {
|
||||||
return ANY_TYPE;
|
return ANY_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isAny(JetType type) {
|
||||||
|
return !(type instanceof NamespaceType) &&
|
||||||
|
type.getConstructor() == ANY_TYPE.getConstructor();
|
||||||
|
}
|
||||||
|
|
||||||
public static JetType getNullableAnyType() {
|
public static JetType getNullableAnyType() {
|
||||||
return NULLABLE_ANY_TYPE;
|
return NULLABLE_ANY_TYPE;
|
||||||
|
|||||||
+18
-4
@@ -110,11 +110,15 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetType visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context) {
|
public JetType visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context) {
|
||||||
|
return visitParenthesizedExpression(expression, context, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JetType visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
||||||
JetExpression innerExpression = expression.getExpression();
|
JetExpression innerExpression = expression.getExpression();
|
||||||
if (innerExpression == null) {
|
if (innerExpression == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkType(facade.getType(innerExpression, context.replaceScope(context.scope)), expression, context);
|
return DataFlowUtils.checkType(facade.getType(innerExpression, context.replaceScope(context.scope), isStatement), expression, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -479,7 +483,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetType visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context) {
|
public JetType visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context) {
|
||||||
return context.getServices().getBlockReturnedType(context.scope, expression, CoercionStrategy.NO_COERCION, context);
|
return visitBlockExpression(expression, context, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JetType visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
||||||
|
return context.getServices().getBlockReturnedType(context.scope, expression, isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -611,6 +619,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetType visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context) {
|
public JetType visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context) {
|
||||||
|
return visitUnaryExpression(expression, context, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JetType visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
||||||
JetExpression baseExpression = expression.getBaseExpression();
|
JetExpression baseExpression = expression.getBaseExpression();
|
||||||
if (baseExpression == null) return null;
|
if (baseExpression == null) return null;
|
||||||
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
||||||
@@ -619,9 +631,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
referencedName = referencedName == null ? " <?>" : referencedName;
|
referencedName = referencedName == null ? " <?>" : referencedName;
|
||||||
context.labelResolver.enterLabeledElement(referencedName.substring(1), baseExpression);
|
context.labelResolver.enterLabeledElement(referencedName.substring(1), baseExpression);
|
||||||
// TODO : Some processing for the label?
|
// TODO : Some processing for the label?
|
||||||
JetType type = DataFlowUtils.checkType(facade.getType(baseExpression, context.replaceExpectedReturnType(context.expectedType)), expression, context);
|
ExpressionTypingContext newContext = context.replaceExpectedReturnType(context.expectedType);
|
||||||
|
JetType type = facade.getType(baseExpression, newContext, isStatement);
|
||||||
context.labelResolver.exitLabeledElement(baseExpression);
|
context.labelResolver.exitLabeledElement(baseExpression);
|
||||||
return type;
|
return DataFlowUtils.checkType(type, expression, context);
|
||||||
}
|
}
|
||||||
IElementType operationType = operationSign.getReferencedNameElementType();
|
IElementType operationType = operationSign.getReferencedNameElementType();
|
||||||
String name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType);
|
String name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType);
|
||||||
@@ -835,6 +848,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private JetType assignmentIsNotAnExpressionError(JetBinaryExpression expression, ExpressionTypingContext context) {
|
private JetType assignmentIsNotAnExpressionError(JetBinaryExpression expression, ExpressionTypingContext context) {
|
||||||
|
facade.checkStatementType(expression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||||
context.trace.report(ASSIGNMENT_IN_EXPRESSION_CONTEXT.on(expression));
|
context.trace.report(ASSIGNMENT_IN_EXPRESSION_CONTEXT.on(expression));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-13
@@ -12,8 +12,6 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
|
|||||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
|
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.TaskPrioritizers;
|
|
||||||
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.autocasts.DataFlowInfo;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||||
@@ -54,7 +52,11 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetType visitIfExpression(JetIfExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
public JetType visitIfExpression(JetIfExpression expression, ExpressionTypingContext context) {
|
||||||
|
return visitIfExpression(expression, context, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JetType visitIfExpression(JetIfExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
||||||
JetExpression condition = expression.getCondition();
|
JetExpression condition = expression.getCondition();
|
||||||
checkCondition(context.scope, condition, context);
|
checkCondition(context.scope, condition, context);
|
||||||
@@ -73,7 +75,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
if (type != null && JetStandardClasses.isNothing(type)) {
|
if (type != null && JetStandardClasses.isNothing(type)) {
|
||||||
facade.setResultingDataFlowInfo(elseInfo);
|
facade.setResultingDataFlowInfo(elseInfo);
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType);
|
return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, contextWithExpectedType, isStatement);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -82,10 +84,11 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
if (type != null && JetStandardClasses.isNothing(type)) {
|
if (type != null && JetStandardClasses.isNothing(type)) {
|
||||||
facade.setResultingDataFlowInfo(thenInfo);
|
facade.setResultingDataFlowInfo(thenInfo);
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType);
|
return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, contextWithExpectedType, isStatement);
|
||||||
}
|
}
|
||||||
JetType thenType = context.getServices().getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), CoercionStrategy.NO_COERCION, contextWithExpectedType.replaceDataFlowInfo(thenInfo));
|
CoercionStrategy coercionStrategy = isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION;
|
||||||
JetType elseType = context.getServices().getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), CoercionStrategy.NO_COERCION, contextWithExpectedType.replaceDataFlowInfo(elseInfo));
|
JetType thenType = context.getServices().getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), coercionStrategy, contextWithExpectedType.replaceDataFlowInfo(thenInfo));
|
||||||
|
JetType elseType = context.getServices().getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), coercionStrategy, contextWithExpectedType.replaceDataFlowInfo(elseInfo));
|
||||||
|
|
||||||
JetType result;
|
JetType result;
|
||||||
if (thenType == null) {
|
if (thenType == null) {
|
||||||
@@ -107,11 +110,18 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
else if (jumpInElse && !jumpInThen) {
|
else if (jumpInElse && !jumpInThen) {
|
||||||
facade.setResultingDataFlowInfo(thenInfo);
|
facade.setResultingDataFlowInfo(thenInfo);
|
||||||
}
|
}
|
||||||
return result;
|
if (result == null) return null;
|
||||||
|
return DataFlowUtils.checkImplicitCast(result, expression, contextWithExpectedType, isStatement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetType visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
public JetType visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext context) {
|
||||||
|
return visitWhileExpression(expression, context, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JetType visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||||
|
if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
|
||||||
|
|
||||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
||||||
JetExpression condition = expression.getCondition();
|
JetExpression condition = expression.getCondition();
|
||||||
checkCondition(context.scope, condition, context);
|
checkCondition(context.scope, condition, context);
|
||||||
@@ -152,7 +162,12 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetType visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
public JetType visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext context) {
|
||||||
|
return visitDoWhileExpression(expression, context, false);
|
||||||
|
}
|
||||||
|
public JetType visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||||
|
if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
|
||||||
|
|
||||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
||||||
JetExpression body = expression.getBody();
|
JetExpression body = expression.getBody();
|
||||||
JetScope conditionScope = context.scope;
|
JetScope conditionScope = context.scope;
|
||||||
@@ -181,7 +196,13 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetType visitForExpression(JetForExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
public JetType visitForExpression(JetForExpression expression, ExpressionTypingContext context) {
|
||||||
|
return visitForExpression(expression, context, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JetType visitForExpression(JetForExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||||
|
if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
|
||||||
|
|
||||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
||||||
JetParameter loopParameter = expression.getLoopParameter();
|
JetParameter loopParameter = expression.getLoopParameter();
|
||||||
JetExpression loopRange = expression.getLoopRange();
|
JetExpression loopRange = expression.getLoopRange();
|
||||||
@@ -419,6 +440,4 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
context.labelResolver.recordLabel(expression, context);
|
context.labelResolver.recordLabel(expression, context);
|
||||||
return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context);
|
return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
|||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||||
|
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||||
@@ -18,8 +19,7 @@ import org.jetbrains.jet.lexer.JetTokens;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.AUTOCAST_IMPOSSIBLE;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.TYPE_MISMATCH;
|
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.AUTOCAST;
|
import static org.jetbrains.jet.lang.resolve.BindingContext.AUTOCAST;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -154,4 +154,30 @@ public class DataFlowUtils {
|
|||||||
context.trace.report(TYPE_MISMATCH.on(expression, context.expectedType, expressionType));
|
context.trace.report(TYPE_MISMATCH.on(expression, context.expectedType, expressionType));
|
||||||
return expressionType;
|
return expressionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static JetType checkStatementType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context) {
|
||||||
|
if (context.expectedType != TypeUtils.NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(context.expectedType)) {
|
||||||
|
context.trace.report(EXPECTED_TYPE_MISMATCH.on(expression, context.expectedType));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return JetStandardClasses.getUnitType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static JetType checkImplicitCast(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ExpressionTypingContext context, boolean isStatement) {
|
||||||
|
if (expressionType != null && context.expectedType == TypeUtils.NO_EXPECTED_TYPE && !isStatement &&
|
||||||
|
(JetStandardClasses.isUnit(expressionType) || JetStandardClasses.isAny(expressionType))) {
|
||||||
|
context.trace.report(IMPLICIT_CAST_TO_UNIT_OR_ANY.on(expression, expressionType));
|
||||||
|
|
||||||
|
}
|
||||||
|
return expressionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static JetType illegalStatementType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context, @NotNull ExpressionTypingInternals facade) {
|
||||||
|
facade.checkStatementType(expression, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE));
|
||||||
|
context.trace.report(EXPRESSION_EXPECTED.on(expression, expression));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -14,7 +14,7 @@ public interface ExpressionTypingFacade {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context);
|
JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context);
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
JetType getTypeForStatement(@NotNull JetExpression expression, ExpressionTypingContext context);
|
JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -24,4 +24,6 @@ import org.jetbrains.jet.lang.types.JetType;
|
|||||||
JetType getSelectorReturnType(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression selectorExpression, @NotNull ExpressionTypingContext context);
|
JetType getSelectorReturnType(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression selectorExpression, @NotNull ExpressionTypingContext context);
|
||||||
|
|
||||||
void checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @NotNull JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context);
|
void checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @NotNull JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context);
|
||||||
|
|
||||||
|
void checkStatementType(@NotNull JetExpression expression, ExpressionTypingContext context);
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -133,7 +133,7 @@ public class ExpressionTypingServices {
|
|||||||
getBlockReturnedType(newContext.scope, blockExpression, CoercionStrategy.COERCION_TO_UNIT, context);
|
getBlockReturnedType(newContext.scope, blockExpression, CoercionStrategy.COERCION_TO_UNIT, context);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
expressionTypingFacade.getType(bodyExpression, newContext);
|
expressionTypingFacade.getType(bodyExpression, newContext, !blockBody);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ public class ExpressionTypingServices {
|
|||||||
assert bodyExpression != null;
|
assert bodyExpression != null;
|
||||||
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
|
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
|
||||||
expressionTypingFacade.getType(bodyExpression, ExpressionTypingContext.newContext(semanticServices, new HashMap<JetPattern, DataFlowInfo>(), new HashMap<JetPattern, List<VariableDescriptor>>(), new LabelResolver(),
|
expressionTypingFacade.getType(bodyExpression, ExpressionTypingContext.newContext(semanticServices, new HashMap<JetPattern, DataFlowInfo>(), new HashMap<JetPattern, List<VariableDescriptor>>(), new LabelResolver(),
|
||||||
trace, functionInnerScope, DataFlowInfo.EMPTY, NO_EXPECTED_TYPE, FORBIDDEN, false));
|
trace, functionInnerScope, DataFlowInfo.EMPTY, NO_EXPECTED_TYPE, FORBIDDEN, false), !function.hasBlockBody());
|
||||||
//todo function literals
|
//todo function literals
|
||||||
final Collection<JetExpression> returnedExpressions = Lists.newArrayList();
|
final Collection<JetExpression> returnedExpressions = Lists.newArrayList();
|
||||||
if (function.hasBlockBody()) {
|
if (function.hasBlockBody()) {
|
||||||
@@ -225,13 +225,13 @@ public class ExpressionTypingServices {
|
|||||||
final boolean[] mismatch = new boolean[1];
|
final boolean[] mismatch = new boolean[1];
|
||||||
ObservableBindingTrace errorInterceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceExpectingUnit, statementExpression, mismatch);
|
ObservableBindingTrace errorInterceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceExpectingUnit, statementExpression, mismatch);
|
||||||
newContext = createContext(newContext, errorInterceptingTrace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
|
newContext = createContext(newContext, errorInterceptingTrace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
|
||||||
result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext);
|
result = blockLevelVisitor.getType(statementExpression, newContext, true);
|
||||||
if (mismatch[0]) {
|
if (mismatch[0]) {
|
||||||
TemporaryBindingTrace temporaryTraceNoExpectedType = TemporaryBindingTrace.create(trace);
|
TemporaryBindingTrace temporaryTraceNoExpectedType = TemporaryBindingTrace.create(trace);
|
||||||
mismatch[0] = false;
|
mismatch[0] = false;
|
||||||
ObservableBindingTrace interceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceNoExpectedType, statementExpression, mismatch);
|
ObservableBindingTrace interceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceNoExpectedType, statementExpression, mismatch);
|
||||||
newContext = createContext(newContext, interceptingTrace, scope, newContext.dataFlowInfo, NO_EXPECTED_TYPE, context.expectedReturnType);
|
newContext = createContext(newContext, interceptingTrace, scope, newContext.dataFlowInfo, NO_EXPECTED_TYPE, context.expectedReturnType);
|
||||||
result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext);
|
result = blockLevelVisitor.getType(statementExpression, newContext, true);
|
||||||
if (mismatch[0]) {
|
if (mismatch[0]) {
|
||||||
temporaryTraceExpectingUnit.commit();
|
temporaryTraceExpectingUnit.commit();
|
||||||
}
|
}
|
||||||
@@ -245,11 +245,11 @@ public class ExpressionTypingServices {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
newContext = createContext(newContext, trace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
|
newContext = createContext(newContext, trace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
|
||||||
result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext);
|
result = blockLevelVisitor.getType(statementExpression, newContext, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext);
|
result = blockLevelVisitor.getType(statementExpression, newContext, true);
|
||||||
if (coercionStrategyForLastExpression == CoercionStrategy.COERCION_TO_UNIT) {
|
if (coercionStrategyForLastExpression == CoercionStrategy.COERCION_TO_UNIT) {
|
||||||
boolean mightBeUnit = false;
|
boolean mightBeUnit = false;
|
||||||
if (statementExpression instanceof JetDeclaration) {
|
if (statementExpression instanceof JetDeclaration) {
|
||||||
@@ -271,7 +271,7 @@ public class ExpressionTypingServices {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext);
|
result = blockLevelVisitor.getType(statementExpression, newContext, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
DataFlowInfo newDataFlowInfo = blockLevelVisitor.getResultingDataFlowInfo();
|
DataFlowInfo newDataFlowInfo = blockLevelVisitor.getResultingDataFlowInfo();
|
||||||
|
|||||||
+16
-4
@@ -40,7 +40,7 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetType, Expre
|
|||||||
private ExpressionTypingVisitorDispatcher(WritableScope writableScope) {
|
private ExpressionTypingVisitorDispatcher(WritableScope writableScope) {
|
||||||
this.basic = new BasicExpressionTypingVisitor(this);
|
this.basic = new BasicExpressionTypingVisitor(this);
|
||||||
if (writableScope != null) {
|
if (writableScope != null) {
|
||||||
this.statements = new ExpressionTypingVisitorForStatements(this, writableScope, basic);
|
this.statements = new ExpressionTypingVisitorForStatements(this, writableScope, basic, controlStructures, patterns);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.statements = null;
|
this.statements = null;
|
||||||
@@ -84,10 +84,22 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetType, Expre
|
|||||||
return getType(expression, context, this);
|
return getType(expression, context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public final JetType getTypeForStatement(@NotNull JetExpression expression, ExpressionTypingContext context) {
|
public final JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
||||||
return getType(expression, context, statements);
|
if (!isStatement) return getType(expression, context);
|
||||||
|
if (statements != null) {
|
||||||
|
return getType(expression, context, statements);
|
||||||
|
}
|
||||||
|
return getType(expression, context, createStatementVisitor(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ExpressionTypingVisitorForStatements createStatementVisitor(ExpressionTypingContext context) {
|
||||||
|
return new ExpressionTypingVisitorForStatements(this, ExpressionTypingUtils.newWritableScopeImpl(context).setDebugName("statement scope"), basic, controlStructures, patterns);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkStatementType(@NotNull JetExpression expression, ExpressionTypingContext context) {
|
||||||
|
expression.accept(createStatementVisitor(context), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
+61
-24
@@ -1,6 +1,5 @@
|
|||||||
package org.jetbrains.jet.lang.types.expressions;
|
package org.jetbrains.jet.lang.types.expressions;
|
||||||
|
|
||||||
import com.intellij.openapi.util.Pair;
|
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -32,22 +31,20 @@ import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.get
|
|||||||
public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisitor {
|
public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisitor {
|
||||||
private final WritableScope scope;
|
private final WritableScope scope;
|
||||||
private final BasicExpressionTypingVisitor basic;
|
private final BasicExpressionTypingVisitor basic;
|
||||||
|
private final ControlStructureTypingVisitor controlStructures;
|
||||||
|
private final PatternMatchingTypingVisitor patterns;
|
||||||
|
|
||||||
public ExpressionTypingVisitorForStatements(@NotNull ExpressionTypingInternals facade, @NotNull WritableScope scope, BasicExpressionTypingVisitor basic) {
|
public ExpressionTypingVisitorForStatements(
|
||||||
|
@NotNull ExpressionTypingInternals facade,
|
||||||
|
@NotNull WritableScope scope,
|
||||||
|
BasicExpressionTypingVisitor basic,
|
||||||
|
@NotNull ControlStructureTypingVisitor controlStructures,
|
||||||
|
@NotNull PatternMatchingTypingVisitor patterns) {
|
||||||
super(facade);
|
super(facade);
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
this.basic = basic;
|
this.basic = basic;
|
||||||
}
|
this.controlStructures = controlStructures;
|
||||||
|
this.patterns = patterns;
|
||||||
@Nullable
|
|
||||||
private JetType checkExpectedType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context) {
|
|
||||||
if (context.expectedType != TypeUtils.NO_EXPECTED_TYPE) {
|
|
||||||
if (JetStandardClasses.isUnit(context.expectedType)) {
|
|
||||||
return JetStandardClasses.getUnitType();
|
|
||||||
}
|
|
||||||
context.trace.report(EXPECTED_TYPE_MISMATCH.on(expression, context.expectedType));
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -57,7 +54,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
context.trace.report(Errors.ASSIGNMENT_TYPE_MISMATCH.on(expression, context.expectedType));
|
context.trace.report(Errors.ASSIGNMENT_TYPE_MISMATCH.on(expression, context.expectedType));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return checkExpectedType(expression, context);
|
return DataFlowUtils.checkStatementType(expression, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -68,7 +65,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
PropertyDescriptor propertyDescriptor = context.getDescriptorResolver().resolveObjectDeclarationAsPropertyDescriptor(scope.getContainingDeclaration(), declaration, classDescriptor);
|
PropertyDescriptor propertyDescriptor = context.getDescriptorResolver().resolveObjectDeclarationAsPropertyDescriptor(scope.getContainingDeclaration(), declaration, classDescriptor);
|
||||||
scope.addVariableDescriptor(propertyDescriptor);
|
scope.addVariableDescriptor(propertyDescriptor);
|
||||||
}
|
}
|
||||||
return checkExpectedType(declaration, context);
|
return DataFlowUtils.checkStatementType(declaration, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -103,7 +100,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
}
|
}
|
||||||
|
|
||||||
scope.addVariableDescriptor(propertyDescriptor);
|
scope.addVariableDescriptor(propertyDescriptor);
|
||||||
return checkExpectedType(property, context);
|
return DataFlowUtils.checkStatementType(property, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -112,7 +109,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
scope.addFunctionDescriptor(functionDescriptor);
|
scope.addFunctionDescriptor(functionDescriptor);
|
||||||
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace);
|
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace);
|
||||||
context.getServices().checkFunctionReturnType(functionInnerScope, function, functionDescriptor, context.dataFlowInfo);
|
context.getServices().checkFunctionReturnType(functionInnerScope, function, functionDescriptor, context.dataFlowInfo);
|
||||||
return checkExpectedType(function, context);
|
return DataFlowUtils.checkStatementType(function, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -127,24 +124,24 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetType visitDeclaration(JetDeclaration dcl, ExpressionTypingContext context) {
|
public JetType visitDeclaration(JetDeclaration dcl, ExpressionTypingContext context) {
|
||||||
return checkExpectedType(dcl, context);
|
return DataFlowUtils.checkStatementType(dcl, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetType visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
public JetType visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext context) {
|
||||||
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
||||||
IElementType operationType = operationSign.getReferencedNameElementType();
|
IElementType operationType = operationSign.getReferencedNameElementType();
|
||||||
JetType result;
|
JetType result;
|
||||||
if (operationType == JetTokens.EQ) {
|
if (operationType == JetTokens.EQ) {
|
||||||
result = visitAssignment(expression, contextWithExpectedType);
|
result = visitAssignment(expression, context);
|
||||||
}
|
}
|
||||||
else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
|
else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
|
||||||
result = visitAssignmentOperation(expression, contextWithExpectedType);
|
result = visitAssignmentOperation(expression, context);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return facade.getType(expression, contextWithExpectedType);
|
return facade.getType(expression, context);
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkType(result, expression, contextWithExpectedType);
|
return DataFlowUtils.checkType(result, expression, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected JetType visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
protected JetType visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||||
@@ -218,7 +215,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
if (left instanceof JetSimpleNameExpression) {
|
if (left instanceof JetSimpleNameExpression) {
|
||||||
ExpressionTypingUtils.checkWrappingInRef(left, context);
|
ExpressionTypingUtils.checkWrappingInRef(left, context);
|
||||||
}
|
}
|
||||||
return checkExpectedType(expression, contextWithExpectedType);
|
return DataFlowUtils.checkStatementType(expression, contextWithExpectedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, ExpressionTypingContext context) {
|
private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, ExpressionTypingContext context) {
|
||||||
@@ -259,4 +256,44 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
context.trace.report(UNSUPPORTED.on(element, "in a block"));
|
context.trace.report(UNSUPPORTED.on(element, "in a block"));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetType visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext context) {
|
||||||
|
return controlStructures.visitWhileExpression(expression, context, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetType visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext context) {
|
||||||
|
return controlStructures.visitDoWhileExpression(expression, context, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetType visitForExpression(JetForExpression expression, ExpressionTypingContext context) {
|
||||||
|
return controlStructures.visitForExpression(expression, context, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetType visitIfExpression(JetIfExpression expression, ExpressionTypingContext context) {
|
||||||
|
return controlStructures.visitIfExpression(expression, context, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetType visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext context) {
|
||||||
|
return patterns.visitWhenExpression(expression, context, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetType visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context) {
|
||||||
|
return basic.visitBlockExpression(expression, context, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetType visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context) {
|
||||||
|
return basic.visitParenthesizedExpression(expression, context, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetType visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context) {
|
||||||
|
return basic.visitUnaryExpression(expression, context, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-5
@@ -13,7 +13,6 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
|
|||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
@@ -21,7 +20,6 @@ import org.jetbrains.jet.lang.types.*;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.ensureBooleanResultWithCustomSubject;
|
|
||||||
import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.newWritableScopeImpl;
|
import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.newWritableScopeImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,7 +46,11 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetType visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
public JetType visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext context) {
|
||||||
|
return visitWhenExpression(expression, context, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JetType visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
||||||
// TODO :change scope according to the bound value in the when header
|
// TODO :change scope according to the bound value in the when header
|
||||||
final JetExpression subjectExpression = expression.getSubjectExpression();
|
final JetExpression subjectExpression = expression.getSubjectExpression();
|
||||||
@@ -92,7 +94,9 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
JetExpression bodyExpression = whenEntry.getExpression();
|
JetExpression bodyExpression = whenEntry.getExpression();
|
||||||
if (bodyExpression != null) {
|
if (bodyExpression != null) {
|
||||||
JetType type = facade.getType(bodyExpression, contextWithExpectedType.replaceScope(scopeToExtend).replaceDataFlowInfo(newDataFlowInfo));
|
ExpressionTypingContext newContext = contextWithExpectedType.replaceScope(scopeToExtend).replaceDataFlowInfo(newDataFlowInfo);
|
||||||
|
CoercionStrategy coercionStrategy = isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION;
|
||||||
|
JetType type = context.getServices().getBlockReturnedTypeWithWritableScope(scopeToExtend, Collections.singletonList(bodyExpression), coercionStrategy, newContext);
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
expressionTypes.add(type);
|
expressionTypes.add(type);
|
||||||
}
|
}
|
||||||
@@ -100,7 +104,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!expressionTypes.isEmpty()) {
|
if (!expressionTypes.isEmpty()) {
|
||||||
return CommonSupertypes.commonSupertype(expressionTypes);
|
return DataFlowUtils.checkImplicitCast(CommonSupertypes.commonSupertype(expressionTypes), expression, contextWithExpectedType, isStatement);
|
||||||
}
|
}
|
||||||
else if (expression.getEntries().isEmpty()) {
|
else if (expression.getEntries().isEmpty()) {
|
||||||
// context.trace.getErrorHandler().genericError(expression.getNode(), "Entries required for when-expression");
|
// context.trace.getErrorHandler().genericError(expression.getNode(), "Entries required for when-expression");
|
||||||
|
|||||||
+126
@@ -0,0 +1,126 @@
|
|||||||
|
namespace kt770_351_735
|
||||||
|
|
||||||
|
//+JDK
|
||||||
|
|
||||||
|
//KT-770 Reference is not resolved to anything, but is not marked unresolved
|
||||||
|
fun main(args : Array<String>) {
|
||||||
|
var i = 0
|
||||||
|
when (i) {
|
||||||
|
1 => i--
|
||||||
|
2 => i = 2 // i is surrounded by a black border
|
||||||
|
else => <!UNRESOLVED_REFERENCE!>j<!> = 2
|
||||||
|
}
|
||||||
|
System.out?.println(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
//KT-351 Distinguish statement and expression positions
|
||||||
|
val w = <!EXPRESSION_EXPECTED!>while (true) {}<!>
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>z<!> = 2
|
||||||
|
val r = { // type fun(): Int is inferred
|
||||||
|
if (true) {
|
||||||
|
2
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
z = <!UNUSED_VALUE!>34<!>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val <!UNUSED_VARIABLE!>f<!>: fun(): Int = <!TYPE_MISMATCH!>r<!>
|
||||||
|
val <!UNUSED_VARIABLE!>g<!>: fun(): Any = r
|
||||||
|
}
|
||||||
|
|
||||||
|
//KT-735 Statements without braces are prohibited on the right side of when entries.
|
||||||
|
fun box() : Int {
|
||||||
|
val d = 2
|
||||||
|
var z = 0
|
||||||
|
when(d) {
|
||||||
|
is 5, is 3 => z++
|
||||||
|
else => z = -1000
|
||||||
|
}
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
|
||||||
|
//More tests
|
||||||
|
|
||||||
|
fun test1() = while(true) {}
|
||||||
|
fun test2(): Unit = while(true) {}
|
||||||
|
|
||||||
|
fun testCoercionToUnit() {
|
||||||
|
val <!UNUSED_VARIABLE!>simple<!>: fun(): Unit = {
|
||||||
|
41
|
||||||
|
}
|
||||||
|
val <!UNUSED_VARIABLE!>withIf<!>: fun(): Unit = {
|
||||||
|
if (true) {
|
||||||
|
3
|
||||||
|
} else {
|
||||||
|
45
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val i = 34
|
||||||
|
val <!UNUSED_VARIABLE!>withWhen<!> : fun() : Unit = {
|
||||||
|
when(i) {
|
||||||
|
is 1 => {
|
||||||
|
val d = 34
|
||||||
|
"1"
|
||||||
|
doSmth(d)
|
||||||
|
|
||||||
|
}
|
||||||
|
is 2 => '4'
|
||||||
|
else => true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>x<!> = 43
|
||||||
|
val checkType = {
|
||||||
|
if (true) {
|
||||||
|
x = <!UNUSED_VALUE!>4<!>
|
||||||
|
} else {
|
||||||
|
45
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val <!UNUSED_VARIABLE!>f<!> : fun() : String = <!TYPE_MISMATCH!>checkType<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun doSmth(<!UNUSED_PARAMETER!>i<!>: Int) {}
|
||||||
|
|
||||||
|
fun testImplicitCoercion() {
|
||||||
|
val d = 21
|
||||||
|
var z = 0
|
||||||
|
var <!UNUSED_VARIABLE!>i<!> = <!IMPLICIT_CAST_TO_UNIT_OR_ANY!>when(d) {
|
||||||
|
is 3 => null
|
||||||
|
is 4 => { val <!NAME_SHADOWING, UNUSED_VARIABLE!>z<!> = 23 }
|
||||||
|
else => z = 20
|
||||||
|
}<!>
|
||||||
|
|
||||||
|
var <!UNUSED_VARIABLE!>u<!> = <!IMPLICIT_CAST_TO_UNIT_OR_ANY!>when(d) {
|
||||||
|
is 3 => {
|
||||||
|
z = <!UNUSED_VALUE!>34<!>
|
||||||
|
}
|
||||||
|
else => <!UNUSED_CHANGED_VALUE!>z--<!>
|
||||||
|
}<!>
|
||||||
|
|
||||||
|
var <!UNUSED_VARIABLE!>iff<!> = <!IMPLICIT_CAST_TO_UNIT_OR_ANY!>if (true) {
|
||||||
|
z = <!UNUSED_VALUE!>34<!>
|
||||||
|
}<!>
|
||||||
|
val <!UNUSED_VARIABLE!>g<!> = <!IMPLICIT_CAST_TO_UNIT_OR_ANY!>if (true) 4<!>
|
||||||
|
val <!UNUSED_VARIABLE!>h<!> = <!IMPLICIT_CAST_TO_UNIT_OR_ANY!>if (false) 4 else {}<!>
|
||||||
|
|
||||||
|
bar(if (true) {
|
||||||
|
4
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
z = <!UNUSED_VALUE!>342<!>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bar(<!UNUSED_PARAMETER!>a<!>: Unit) {}
|
||||||
|
|
||||||
|
fun testStatementInExpressionContext() {
|
||||||
|
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>z<!> = 34
|
||||||
|
val <!UNUSED_VARIABLE!>a1<!>: Unit = <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>z = <!UNUSED_VALUE!>334<!><!>
|
||||||
|
val <!UNUSED_VARIABLE!>a2<!>: Unit = <!EXPRESSION_EXPECTED!>while(true) {}<!>
|
||||||
|
val <!UNUSED_VARIABLE!>f<!> = <!EXPRESSION_EXPECTED!>for (i in 1..10) {}<!>
|
||||||
|
if (true) return <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>z = <!UNUSED_VALUE!>34<!><!>
|
||||||
|
return <!EXPRESSION_EXPECTED!>while (true) {}<!>
|
||||||
|
}
|
||||||
@@ -18,6 +18,6 @@ fun box() : Boolean {
|
|||||||
|
|
||||||
|
|
||||||
fun box2() : Boolean {
|
fun box2() : Boolean {
|
||||||
var <!UNUSED_VARIABLE!>c<!> = A()
|
var c = A()
|
||||||
return (<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>c.p = "yeah"<!>) && true
|
return (<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>c.p = "yeah"<!>) && true
|
||||||
}
|
}
|
||||||
@@ -326,9 +326,9 @@ public class JetTypeCheckerTest extends JetLiteFixture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testLoops() throws Exception {
|
public void testLoops() throws Exception {
|
||||||
assertType("while (1) {1}", "Unit");
|
assertType("{ while (1) {1} }", "fun(): Unit");
|
||||||
assertType("do {1} while(1)", "Unit");
|
assertType("{ do {1} while(1) }", "fun(): Unit");
|
||||||
assertType("for (i in 1) {1}", "Unit");
|
assertType("{ for (i in 1) {1} }", "fun(): Unit");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFunctionLiterals() throws Exception {
|
public void testFunctionLiterals() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user