rewrote analyzing expression with type rhs

removed unnecessary temporary trace (and so extra 'getType' for left expression)
This commit is contained in:
Svetlana Isakova
2013-08-08 20:01:23 +04:00
parent 4caeadc0c1
commit 6429239f3f
3 changed files with 39 additions and 53 deletions
@@ -150,71 +150,57 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
@Override @Override
public JetTypeInfo visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression, ExpressionTypingContext context) { public JetTypeInfo visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression, ExpressionTypingContext context) {
ExpressionTypingContext contextWithNoExpectedType =
context.replaceExpectedType(NO_EXPECTED_TYPE).replaceResolveMode(ResolveMode.TOP_LEVEL_CALL);
JetExpression left = expression.getLeft(); JetExpression left = expression.getLeft();
JetTypeReference right = expression.getRight(); JetTypeReference right = expression.getRight();
JetType result = null; if (right == null) {
JetTypeInfo leftTypeInfo = facade.getTypeInfo(left, contextWithNoExpectedType);
return JetTypeInfo.create(null, leftTypeInfo.getDataFlowInfo());
}
JetType targetType = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, right, context.trace, true);
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
if (isTypeFlexible(left) || operationType == JetTokens.COLON) {
JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType.replaceExpectedType(targetType));
checkBinaryWithTypeRHS(expression, context, targetType, typeInfo.getType());
return DataFlowUtils.checkType(targetType, expression, context, typeInfo.getDataFlowInfo());
}
JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType);
DataFlowInfo dataFlowInfo = context.dataFlowInfo; DataFlowInfo dataFlowInfo = context.dataFlowInfo;
if (right != null) { if (typeInfo.getType() != null) {
JetType targetType = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, right, context.trace, true); checkBinaryWithTypeRHS(expression, contextWithNoExpectedType, targetType, typeInfo.getType());
IElementType operationType = expression.getOperationReference().getReferencedNameElementType(); dataFlowInfo = typeInfo.getDataFlowInfo();
if (operationType == JetTokens.AS_KEYWORD) {
boolean tryWithNoExpectedType = true; DataFlowValue value = DataFlowValueFactory.INSTANCE.createDataFlowValue(left, typeInfo.getType(), context.trace.getBindingContext());
if (isTypeFlexible(left) || operationType == JetTokens.COLON) { dataFlowInfo = dataFlowInfo.establishSubtyping(value, targetType);
TemporaryBindingTrace temporaryTraceWithExpectedType = TemporaryBindingTrace.create(
context.trace, "trace for resolve RHSExpression", expression);
ExpressionTypingContext contextWithTemporaryTrace = context.replaceBindingTrace(temporaryTraceWithExpectedType).replaceExpectedType(targetType);
JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithTemporaryTrace);
if (typeInfo.getType() != null && checkBinaryWithTypeRHS(expression, contextWithTemporaryTrace, targetType, typeInfo.getType())) {
temporaryTraceWithExpectedType.commit();
dataFlowInfo = typeInfo.getDataFlowInfo();
tryWithNoExpectedType = false;
}
} }
if (tryWithNoExpectedType) {
ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE);
JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType);
if (typeInfo.getType() != null) {
checkBinaryWithTypeRHS(expression, contextWithNoExpectedType, targetType, typeInfo.getType());
dataFlowInfo = typeInfo.getDataFlowInfo();
if (operationType == JetTokens.AS_KEYWORD) {
DataFlowValue value = DataFlowValueFactory.INSTANCE.createDataFlowValue(left, typeInfo.getType(), context.trace.getBindingContext());
dataFlowInfo = dataFlowInfo.establishSubtyping(value, targetType);
}
}
}
result = operationType == JetTokens.AS_SAFE ? TypeUtils.makeNullable(targetType) : targetType;
}
else {
dataFlowInfo = facade.getTypeInfo(left, context.replaceExpectedType(NO_EXPECTED_TYPE)).getDataFlowInfo();
} }
JetType result = operationType == JetTokens.AS_SAFE ? TypeUtils.makeNullable(targetType) : targetType;
return DataFlowUtils.checkType(result, expression, context, dataFlowInfo); return DataFlowUtils.checkType(result, expression, context, dataFlowInfo);
} }
private static boolean checkBinaryWithTypeRHS( private static void checkBinaryWithTypeRHS(
JetBinaryExpressionWithTypeRHS expression, @NotNull JetBinaryExpressionWithTypeRHS expression,
ExpressionTypingContext context, @NotNull ExpressionTypingContext context,
@NotNull JetType targetType, @NotNull JetType targetType,
JetType actualType @Nullable JetType actualType
) { ) {
if (actualType == null) return;
JetSimpleNameExpression operationSign = expression.getOperationReference(); JetSimpleNameExpression operationSign = expression.getOperationReference();
IElementType operationType = operationSign.getReferencedNameElementType(); IElementType operationType = operationSign.getReferencedNameElementType();
if (operationType == JetTokens.COLON) { if (operationType == JetTokens.COLON) {
if (!noExpectedType(targetType) && !JetTypeChecker.INSTANCE.isSubtypeOf(actualType, targetType)) { return;
context.trace.report(TYPE_MISMATCH.on(expression.getLeft(), targetType, actualType));
return false;
}
return true;
} }
else if (operationType == JetTokens.AS_KEYWORD || operationType == JetTokens.AS_SAFE) { if (operationType != JetTokens.AS_KEYWORD && operationType != JetTokens.AS_SAFE) {
checkForCastImpossibility(expression, actualType, targetType, context);
return true;
}
else {
context.trace.report(UNSUPPORTED.on(operationSign, "binary operation with type RHS")); context.trace.report(UNSUPPORTED.on(operationSign, "binary operation with type RHS"));
return false; return;
} }
checkForCastImpossibility(expression, actualType, targetType, context);
} }
private static void checkForCastImpossibility( private static void checkForCastImpossibility(
@@ -25,15 +25,15 @@ fun test() {
1e5: Double 1e5: Double
1e-5: Float 1e-5: Float
<!TYPE_MISMATCH!>1<!>: Double <!ERROR_COMPILE_TIME_VALUE!>1<!>: Double
<!TYPE_MISMATCH!>1<!>: Float <!ERROR_COMPILE_TIME_VALUE!>1<!>: Float
1 <!USELESS_CAST!>as<!> Byte 1 <!USELESS_CAST!>as<!> Byte
1 <!USELESS_CAST!>as<!> Int 1 <!USELESS_CAST!>as<!> Int
0xff <!USELESS_CAST!>as<!> Long 0xff <!USELESS_CAST!>as<!> Long
<!ERROR_COMPILE_TIME_VALUE!>1.1<!> <!CAST_NEVER_SUCCEEDS!>as<!> Int <!ERROR_COMPILE_TIME_VALUE!>1.1<!> <!CAST_NEVER_SUCCEEDS!>as<!> Int
<!TYPE_MISMATCH!>1.1<!>: Int <!ERROR_COMPILE_TIME_VALUE!>1.1<!>: Int
varargByte(0x77, 1, 3, <!ERROR_COMPILE_TIME_VALUE!>200<!>, 0b111) varargByte(0x77, 1, 3, <!ERROR_COMPILE_TIME_VALUE!>200<!>, 0b111)
varargShort(0x777, 1, 2, 3, <!ERROR_COMPILE_TIME_VALUE!>200000<!>, 0b111) varargShort(0x777, 1, 2, 3, <!ERROR_COMPILE_TIME_VALUE!>200000<!>, 0b111)
@@ -31,5 +31,5 @@ fun main(args : Array<String>) {
} }
val <!UNUSED_VARIABLE!>f<!> : String = <!TYPE_MISMATCH!>a<!><!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!> val <!UNUSED_VARIABLE!>f<!> : String = <!TYPE_MISMATCH!>a<!><!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
<!TYPE_MISMATCH!>a<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!><!> : String <!TYPE_MISMATCH!>a<!><!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!> : String
} }