analyze a lot of expressions in independent of context (expected type) mode
This commit is contained in:
+4
-2
@@ -375,8 +375,10 @@ public class CallExpressionResolver {
|
||||
// TODO : functions as values
|
||||
JetExpression selectorExpression = expression.getSelectorExpression();
|
||||
JetExpression receiverExpression = expression.getReceiverExpression();
|
||||
JetTypeInfo receiverTypeInfo = expressionTypingServices.getTypeInfoWithNamespaces(
|
||||
receiverExpression, context.scope, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace);
|
||||
ResolutionContext contextForReceiver = context
|
||||
.replaceExpectedType(NO_EXPECTED_TYPE).replaceExpressionPosition(ExpressionPosition.LHS_OF_DOT)
|
||||
.replaceContextDependency(ContextDependency.INDEPENDENT);
|
||||
JetTypeInfo receiverTypeInfo = expressionTypingServices.getTypeInfo(receiverExpression, contextForReceiver);
|
||||
JetType receiverType = receiverTypeInfo.getType();
|
||||
if (selectorExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
if (receiverType == null) receiverType = ErrorUtils.createErrorType("Type for " + expression.getText());
|
||||
|
||||
@@ -363,7 +363,8 @@ public class CandidateResolver {
|
||||
}
|
||||
|
||||
CallCandidateResolutionContext<FunctionDescriptor> contextForArgument = storedContextForArgument
|
||||
.replaceContextDependency(ContextDependency.INDEPENDENT).replaceBindingTrace(context.trace).replaceExpectedType(expectedType);
|
||||
.replaceContextDependency(ContextDependency.INDEPENDENT).replaceBindingTrace(context.trace).replaceExpectedType(
|
||||
expectedType);
|
||||
JetType type;
|
||||
if (contextForArgument.candidateCall.hasIncompleteTypeParameters()) {
|
||||
type = completeTypeInferenceDependentOnExpectedTypeForCall(contextForArgument, true);
|
||||
@@ -402,16 +403,29 @@ public class CandidateResolver {
|
||||
return baseExpression != null ? baseExpression : expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetExpression visitBlockExpression(JetBlockExpression expression, Void data) {
|
||||
JetElement lastStatement = JetPsiUtil.getLastStatementInABlock(expression);
|
||||
if (lastStatement != null) {
|
||||
return lastStatement.accept(this, data);
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SuspiciousMethodCalls")
|
||||
@Override
|
||||
public JetExpression visitBinaryExpression(JetBinaryExpression expression, Void data) {
|
||||
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
|
||||
//noinspection SuspiciousMethodCalls
|
||||
if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationType)) {
|
||||
//Result type of comparison doesn't depend on expected type:
|
||||
//it's 'Boolean', but 'compareTo' should return 'Int'.
|
||||
//So we shouldn't check result type of such a call('Int') at completion phase.
|
||||
return null;
|
||||
}
|
||||
if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
|
||||
//the same, result type is always 'Unit'
|
||||
return null;
|
||||
}
|
||||
return super.visitBinaryExpression(expression, data);
|
||||
}
|
||||
};
|
||||
|
||||
+32
-29
@@ -65,6 +65,8 @@ import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getStaticNestedClassesScope;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.DEPENDENT;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
|
||||
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
|
||||
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||
import static org.jetbrains.jet.lang.types.TypeUtils.UNKNOWN_EXPECTED_TYPE;
|
||||
@@ -152,7 +154,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
@Override
|
||||
public JetTypeInfo visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression, ExpressionTypingContext context) {
|
||||
ExpressionTypingContext contextWithNoExpectedType =
|
||||
context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(ContextDependency.INDEPENDENT);
|
||||
context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
|
||||
JetExpression left = expression.getLeft();
|
||||
JetTypeReference right = expression.getRight();
|
||||
if (right == null) {
|
||||
@@ -658,11 +660,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
ReceiverValue receiver = new TransientReceiver(lhsType);
|
||||
TemporaryTraceAndCache temporaryWithReceiver = TemporaryTraceAndCache.create(context,
|
||||
"trace to resolve callable reference with receiver", reference);
|
||||
FunctionDescriptor descriptor =
|
||||
resolveCallableNotCheckingArguments(
|
||||
reference, receiver, context.replaceTraceAndCache(temporaryWithReceiver), result);
|
||||
TemporaryTraceAndCache temporaryWithReceiver = TemporaryTraceAndCache.create(
|
||||
context, "trace to resolve callable reference with receiver", reference);
|
||||
FunctionDescriptor descriptor = resolveCallableNotCheckingArguments(
|
||||
reference, receiver, context.replaceTraceAndCache(temporaryWithReceiver), result);
|
||||
if (result[0]) {
|
||||
temporaryWithReceiver.commit();
|
||||
return descriptor;
|
||||
@@ -743,7 +744,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
// Type check the base expression
|
||||
JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||
JetTypeInfo typeInfo = facade.getTypeInfo(
|
||||
baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT));
|
||||
JetType type = typeInfo.getType();
|
||||
if (type == null) {
|
||||
return typeInfo;
|
||||
@@ -882,8 +884,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetTypeInfo visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
|
||||
public JetTypeInfo visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext context) {
|
||||
ExpressionTypingContext independentContext = context.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE);
|
||||
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
||||
|
||||
JetExpression left = expression.getLeft();
|
||||
@@ -906,15 +908,14 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
dataFlowInfo = typeInfo.getDataFlowInfo();
|
||||
}
|
||||
else if (operationType == JetTokens.EQ) {
|
||||
result = visitAssignment(expression, contextWithExpectedType);
|
||||
result = visitAssignment(expression, context);
|
||||
}
|
||||
else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
|
||||
result = visitAssignmentOperation(expression, contextWithExpectedType);
|
||||
result = visitAssignmentOperation(expression, context);
|
||||
}
|
||||
else if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationType)) {
|
||||
//we don't complete 'compareTo' call, because we change its result type from 'Int' to 'Boolean'
|
||||
JetTypeInfo typeInfo = getTypeInfoForBinaryCall(
|
||||
context.scope, OperatorConventions.COMPARE_TO, context.replaceContextDependency(ContextDependency.INDEPENDENT), expression);
|
||||
JetTypeInfo typeInfo = getTypeInfoForBinaryCall(context.scope, OperatorConventions.COMPARE_TO, independentContext, expression);
|
||||
dataFlowInfo = typeInfo.getDataFlowInfo();
|
||||
JetType compareToReturnType = typeInfo.getType();
|
||||
if (compareToReturnType != null && !ErrorUtils.isErrorType(compareToReturnType)) {
|
||||
@@ -933,12 +934,12 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
JetType booleanType = KotlinBuiltIns.getInstance().getBooleanType();
|
||||
if (OperatorConventions.EQUALS_OPERATIONS.contains(operationType)) {
|
||||
if (right != null && left != null) {
|
||||
ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, context);
|
||||
ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, independentContext);
|
||||
|
||||
JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context, facade);
|
||||
JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, independentContext, facade);
|
||||
|
||||
dataFlowInfo = leftTypeInfo.getDataFlowInfo();
|
||||
ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
|
||||
ExpressionTypingContext contextWithDataFlow = independentContext.replaceDataFlowInfo(dataFlowInfo);
|
||||
|
||||
OverloadResolutionResults<FunctionDescriptor> resolutionResults = resolveFakeCall(
|
||||
contextWithDataFlow, receiver, OperatorConventions.EQUALS, KotlinBuiltIns.getInstance().getNullableAnyType());
|
||||
@@ -950,7 +951,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
context.trace.record(REFERENCE_TARGET, operationSign, equals);
|
||||
context.trace.record(RESOLVED_CALL, operationSign, resolutionResults.getResultingCall());
|
||||
if (ensureBooleanResult(operationSign, OperatorConventions.EQUALS, equals.getReturnType(), context)) {
|
||||
ensureNonemptyIntersectionOfOperandTypes(expression, context);
|
||||
ensureNonemptyIntersectionOfOperandTypes(expression, independentContext);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -965,7 +966,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
result = booleanType;
|
||||
}
|
||||
else if (operationType == JetTokens.EQEQEQ || operationType == JetTokens.EXCLEQEQEQ) {
|
||||
ensureNonemptyIntersectionOfOperandTypes(expression, context);
|
||||
ensureNonemptyIntersectionOfOperandTypes(expression, independentContext);
|
||||
|
||||
// TODO : Check comparison pointlessness
|
||||
result = booleanType;
|
||||
@@ -974,12 +975,12 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (right == null) {
|
||||
return JetTypeInfo.create(null, dataFlowInfo);
|
||||
}
|
||||
JetTypeInfo typeInfo = checkInExpression(expression, expression.getOperationReference(), left, right, context);
|
||||
JetTypeInfo typeInfo = checkInExpression(expression, expression.getOperationReference(), left, right, independentContext);
|
||||
dataFlowInfo = typeInfo.getDataFlowInfo();
|
||||
result = typeInfo.getType();
|
||||
}
|
||||
else if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationType)) {
|
||||
JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context, facade);
|
||||
JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, independentContext, facade);
|
||||
|
||||
JetType leftType = leftTypeInfo.getType();
|
||||
dataFlowInfo = leftTypeInfo.getDataFlowInfo();
|
||||
@@ -991,9 +992,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
WritableScopeImpl rightScope = operationType == JetTokens.ANDAND
|
||||
? leftScope
|
||||
: newWritableScopeImpl(context, "Right scope of && or ||");
|
||||
JetType rightType = right == null
|
||||
? null
|
||||
: facade.getTypeInfo(right, context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope)).getType();
|
||||
ExpressionTypingContext contextForRightExpr = independentContext.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope);
|
||||
JetType rightType = right != null ? facade.getTypeInfo(right, contextForRightExpr).getType() : null;
|
||||
if (left != null && leftType != null && !isBoolean(leftType)) {
|
||||
context.trace.report(TYPE_MISMATCH.on(left, booleanType, leftType));
|
||||
}
|
||||
@@ -1003,13 +1003,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
result = booleanType;
|
||||
}
|
||||
else if (operationType == JetTokens.ELVIS) {
|
||||
return visitElvisExpression(expression, contextWithExpectedType);
|
||||
return visitElvisExpression(expression, context);
|
||||
}
|
||||
else {
|
||||
context.trace.report(UNSUPPORTED.on(operationSign, "Unknown operation"));
|
||||
}
|
||||
}
|
||||
return DataFlowUtils.checkType(result, expression, contextWithExpectedType, dataFlowInfo);
|
||||
return DataFlowUtils.checkType(result, expression, context, dataFlowInfo);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -1134,7 +1134,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
private JetType assignmentIsNotAnExpressionError(JetBinaryExpression expression, ExpressionTypingContext context) {
|
||||
facade.checkStatementType(expression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||
facade.checkStatementType(expression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT));
|
||||
context.trace.report(ASSIGNMENT_IN_EXPRESSION_CONTEXT.on(expression));
|
||||
return null;
|
||||
}
|
||||
@@ -1156,7 +1156,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
JetExpression left = binaryExpression.getLeft();
|
||||
DataFlowInfo dataFlowInfo = context.dataFlowInfo;
|
||||
if (left != null) {
|
||||
dataFlowInfo = facade.getTypeInfo(left, context).getDataFlowInfo();
|
||||
//left here is a receiver, so it doesn't depend on context
|
||||
dataFlowInfo = facade.getTypeInfo(
|
||||
left, context.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE)).getDataFlowInfo();
|
||||
}
|
||||
ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
|
||||
|
||||
@@ -1212,7 +1214,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
@Override
|
||||
public JetTypeInfo visitStringTemplateExpression(JetStringTemplateExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||
final ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
|
||||
final ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
final CompileTimeConstant<?>[] value = new CompileTimeConstant<?>[1];
|
||||
final DataFlowInfo[] dataFlowInfo = new DataFlowInfo[1];
|
||||
@@ -1291,7 +1293,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
JetExpression arrayExpression = arrayAccessExpression.getArrayExpression();
|
||||
if (arrayExpression == null) return JetTypeInfo.create(null, oldContext.dataFlowInfo);
|
||||
|
||||
JetTypeInfo arrayTypeInfo = facade.getTypeInfo(arrayExpression, oldContext.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||
JetTypeInfo arrayTypeInfo = facade.getTypeInfo(arrayExpression, oldContext.replaceExpectedType(NO_EXPECTED_TYPE)
|
||||
.replaceContextDependency(INDEPENDENT));
|
||||
JetType arrayType = arrayTypeInfo.getType();
|
||||
if (arrayType == null) return arrayTypeInfo;
|
||||
|
||||
|
||||
+2
-1
@@ -43,6 +43,7 @@ import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.*;
|
||||
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.expressions.CoercionStrategy.COERCION_TO_UNIT;
|
||||
@@ -84,7 +85,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
|
||||
};
|
||||
ObservableBindingTrace traceAdapter = new ObservableBindingTrace(temporaryTrace);
|
||||
traceAdapter.addHandler(CLASS, handler);
|
||||
TopDownAnalyzer.processClassOrObject(context.replaceBindingTrace(traceAdapter),
|
||||
TopDownAnalyzer.processClassOrObject(context.replaceBindingTrace(traceAdapter).replaceContextDependency(INDEPENDENT),
|
||||
context.scope.getContainingDeclaration(),
|
||||
expression.getObjectDeclaration());
|
||||
|
||||
|
||||
+27
-15
@@ -52,8 +52,10 @@ import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||
import static org.jetbrains.jet.lang.types.TypeUtils.UNKNOWN_EXPECTED_TYPE;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
|
||||
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.UNKNOWN_EXPECTED_TYPE;
|
||||
import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.*;
|
||||
import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.*;
|
||||
|
||||
@@ -69,7 +71,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
private DataFlowInfo checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition, ExpressionTypingContext context) {
|
||||
if (condition != null) {
|
||||
JetTypeInfo typeInfo = facade.getTypeInfo(condition, context.replaceScope(scope)
|
||||
.replaceExpectedType(KotlinBuiltIns.getInstance().getBooleanType()));
|
||||
.replaceExpectedType(KotlinBuiltIns.getInstance().getBooleanType()).replaceContextDependency(INDEPENDENT));
|
||||
JetType conditionType = typeInfo.getType();
|
||||
|
||||
if (conditionType != null && !isBoolean(conditionType)) {
|
||||
@@ -90,7 +92,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
public JetTypeInfo visitIfExpression(JetIfExpression ifExpression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
|
||||
JetExpression condition = ifExpression.getCondition();
|
||||
DataFlowInfo conditionDataFlowInfo = checkCondition(context.scope, condition, context);
|
||||
|
||||
@@ -171,8 +173,10 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
@NotNull JetIfExpression ifExpression,
|
||||
boolean isStatement
|
||||
) {
|
||||
JetTypeInfo typeInfo = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(presentScope, Collections
|
||||
.singletonList(presentBranch), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(presentInfo), context.trace);
|
||||
ExpressionTypingContext newContext = context.replaceDataFlowInfo(presentInfo).replaceExpectedType(NO_EXPECTED_TYPE)
|
||||
.replaceContextDependency(INDEPENDENT);
|
||||
JetTypeInfo typeInfo = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(
|
||||
presentScope, Collections.singletonList(presentBranch), CoercionStrategy.NO_COERCION, newContext, context.trace);
|
||||
JetType type = typeInfo.getType();
|
||||
DataFlowInfo dataFlowInfo;
|
||||
if (type != null && KotlinBuiltIns.getInstance().isNothing(type)) {
|
||||
@@ -192,7 +196,8 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
public JetTypeInfo 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(NO_EXPECTED_TYPE).replaceContextDependency(
|
||||
INDEPENDENT);
|
||||
JetExpression condition = expression.getCondition();
|
||||
DataFlowInfo dataFlowInfo = checkCondition(context.scope, condition, context);
|
||||
|
||||
@@ -200,7 +205,9 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (body != null) {
|
||||
WritableScopeImpl scopeToExtend = newWritableScopeImpl(context, "Scope extended in while's condition");
|
||||
DataFlowInfo conditionInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, true, context).and(dataFlowInfo);
|
||||
context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(scopeToExtend, Collections.singletonList(body), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(conditionInfo), context.trace);
|
||||
context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(
|
||||
scopeToExtend, Collections.singletonList(body),
|
||||
CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(conditionInfo), context.trace);
|
||||
}
|
||||
|
||||
if (!containsJumpOutOfLoop(expression, context)) {
|
||||
@@ -255,7 +262,8 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
public JetTypeInfo 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(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
|
||||
JetExpression body = expression.getBody();
|
||||
JetScope conditionScope = context.scope;
|
||||
if (body instanceof JetFunctionLiteralExpression) {
|
||||
@@ -304,7 +312,8 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
public JetTypeInfo 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(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
|
||||
JetExpression loopRange = expression.getLoopRange();
|
||||
JetType expectedParameterType = null;
|
||||
DataFlowInfo dataFlowInfo = context.dataFlowInfo;
|
||||
@@ -453,7 +462,8 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetTypeInfo visitTryExpression(JetTryExpression expression, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitTryExpression(JetTryExpression expression, ExpressionTypingContext typingContext) {
|
||||
ExpressionTypingContext context = typingContext.replaceContextDependency(INDEPENDENT);
|
||||
JetExpression tryBlock = expression.getTryBlock();
|
||||
List<JetCatchClause> catchClauses = expression.getCatchClauses();
|
||||
JetFinallySection finallyBlock = expression.getFinallyBlock();
|
||||
@@ -483,7 +493,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
DataFlowInfo dataFlowInfo = context.dataFlowInfo;
|
||||
if (finallyBlock != null) {
|
||||
dataFlowInfo = facade.getTypeInfo(finallyBlock.getFinalExpression(),
|
||||
context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE)).getDataFlowInfo();
|
||||
context.replaceExpectedType(NO_EXPECTED_TYPE)).getDataFlowInfo();
|
||||
}
|
||||
|
||||
JetType type = facade.getTypeInfo(tryBlock, context).getType();
|
||||
@@ -503,7 +513,8 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
JetExpression thrownExpression = expression.getThrownExpression();
|
||||
if (thrownExpression != null) {
|
||||
JetType throwableType = KotlinBuiltIns.getInstance().getThrowable().getDefaultType();
|
||||
facade.getTypeInfo(thrownExpression, context.replaceExpectedType(throwableType).replaceScope(context.scope));
|
||||
facade.getTypeInfo(thrownExpression, context
|
||||
.replaceExpectedType(throwableType).replaceScope(context.scope).replaceContextDependency(INDEPENDENT));
|
||||
}
|
||||
return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getNothingType(), expression, context, context.dataFlowInfo);
|
||||
}
|
||||
@@ -514,7 +525,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
JetExpression returnedExpression = expression.getReturnedExpression();
|
||||
|
||||
JetType expectedType = TypeUtils.NO_EXPECTED_TYPE;
|
||||
JetType expectedType = NO_EXPECTED_TYPE;
|
||||
JetType resultType = KotlinBuiltIns.getInstance().getNothingType();
|
||||
JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, JetDeclaration.class);
|
||||
|
||||
@@ -558,7 +569,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
context.trace.report(RETURN_NOT_ALLOWED.on(expression));
|
||||
resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
|
||||
}
|
||||
else if (expectedType == TypeUtils.NO_EXPECTED_TYPE) {
|
||||
else if (expectedType == NO_EXPECTED_TYPE) {
|
||||
// expectedType is NO_EXPECTED_TYPE iff the return type of the corresponding function descriptor is not computed yet
|
||||
// our temporary policy is to prohibit returns in this case. It mostly applies to local returns in lambdas
|
||||
context.trace.report(RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED.on(expression));
|
||||
@@ -569,7 +580,8 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
}
|
||||
if (returnedExpression != null) {
|
||||
facade.getTypeInfo(returnedExpression, context.replaceExpectedType(expectedType).replaceScope(context.scope));
|
||||
facade.getTypeInfo(returnedExpression, context.replaceExpectedType(expectedType).replaceScope(context.scope)
|
||||
.replaceContextDependency(INDEPENDENT));
|
||||
}
|
||||
else {
|
||||
if (expectedType != null && !noExpectedType(expectedType) && !KotlinBuiltIns.getInstance().isUnit(expectedType)) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.calls.context.ContextDependency;
|
||||
import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
|
||||
@@ -202,7 +203,8 @@ public class DataFlowUtils {
|
||||
|
||||
@NotNull
|
||||
public static JetTypeInfo illegalStatementType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context, @NotNull ExpressionTypingInternals facade) {
|
||||
facade.checkStatementType(expression, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE));
|
||||
facade.checkStatementType(
|
||||
expression, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceContextDependency(ContextDependency.INDEPENDENT));
|
||||
context.trace.report(EXPRESSION_EXPECTED.on(expression, expression));
|
||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
+18
-11
@@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.resolve.ModifiersChecker;
|
||||
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
|
||||
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.TemporaryTraceAndCache;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
|
||||
@@ -48,6 +49,8 @@ import java.util.Collection;
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.VARIABLE_REASSIGNMENT;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.*;
|
||||
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||
import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
|
||||
|
||||
@SuppressWarnings("SuspiciousMethodCalls")
|
||||
@@ -86,7 +89,8 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
|
||||
@Override
|
||||
public JetTypeInfo visitObjectDeclaration(JetObjectDeclaration declaration, ExpressionTypingContext context) {
|
||||
TopDownAnalyzer.processClassOrObject(context.replaceScope(scope), scope.getContainingDeclaration(), declaration);
|
||||
TopDownAnalyzer.processClassOrObject(
|
||||
context.replaceScope(scope).replaceContextDependency(INDEPENDENT), scope.getContainingDeclaration(), declaration);
|
||||
ClassDescriptor classDescriptor = context.trace.getBindingContext().get(BindingContext.CLASS, declaration);
|
||||
if (classDescriptor != null) {
|
||||
VariableDescriptor variableDescriptor = context.expressionTypingServices.getDescriptorResolver()
|
||||
@@ -97,7 +101,8 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetTypeInfo visitProperty(JetProperty property, ExpressionTypingContext context) {
|
||||
public JetTypeInfo visitProperty(JetProperty property, ExpressionTypingContext typingContext) {
|
||||
ExpressionTypingContext context = typingContext.replaceContextDependency(INDEPENDENT).replaceScope(scope);
|
||||
JetTypeReference receiverTypeRef = property.getReceiverTypeRef();
|
||||
if (receiverTypeRef != null) {
|
||||
context.trace.report(LOCAL_EXTENSION_PROPERTY.on(receiverTypeRef));
|
||||
@@ -115,7 +120,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
|
||||
JetExpression delegateExpression = property.getDelegateExpression();
|
||||
if (delegateExpression != null) {
|
||||
context.expressionTypingServices.getType(scope, delegateExpression, TypeUtils.NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace);
|
||||
context.expressionTypingServices.getTypeInfo(delegateExpression, context);
|
||||
context.trace.report(LOCAL_VARIABLE_WITH_DELEGATE.on(property.getDelegate()));
|
||||
}
|
||||
|
||||
@@ -125,10 +130,10 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
DataFlowInfo dataFlowInfo = context.dataFlowInfo;
|
||||
if (initializer != null) {
|
||||
JetType outType = propertyDescriptor.getType();
|
||||
JetTypeInfo typeInfo = facade.getTypeInfo(initializer, context.replaceExpectedType(outType).replaceScope(scope));
|
||||
JetTypeInfo typeInfo = facade.getTypeInfo(initializer, context.replaceExpectedType(outType));
|
||||
dataFlowInfo = typeInfo.getDataFlowInfo();
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
VariableDescriptor olderVariable = scope.getLocalVariable(propertyDescriptor.getName());
|
||||
ExpressionTypingUtils.checkVariableShadowing(context, propertyDescriptor, olderVariable);
|
||||
@@ -146,8 +151,8 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
context.trace.report(INITIALIZER_REQUIRED_FOR_MULTIDECLARATION.on(multiDeclaration));
|
||||
return JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
}
|
||||
ExpressionReceiver expressionReceiver =
|
||||
ExpressionTypingUtils.getExpressionReceiver(facade, initializer, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE));
|
||||
ExpressionReceiver expressionReceiver = ExpressionTypingUtils.getExpressionReceiver(
|
||||
facade, initializer, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT));
|
||||
DataFlowInfo dataFlowInfo = facade.getTypeInfo(initializer, context).getDataFlowInfo();
|
||||
if (expressionReceiver == null) {
|
||||
return JetTypeInfo.create(null, dataFlowInfo);
|
||||
@@ -171,7 +176,8 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
|
||||
@Override
|
||||
public JetTypeInfo visitClass(JetClass klass, ExpressionTypingContext context) {
|
||||
TopDownAnalyzer.processClassOrObject(context.replaceScope(scope), scope.getContainingDeclaration(), klass);
|
||||
TopDownAnalyzer.processClassOrObject(
|
||||
context.replaceScope(scope).replaceContextDependency(INDEPENDENT), scope.getContainingDeclaration(), klass);
|
||||
ClassDescriptor classDescriptor = context.trace.getBindingContext().get(BindingContext.CLASS, klass);
|
||||
if (classDescriptor != null) {
|
||||
scope.addClassifierDescriptor(classDescriptor);
|
||||
@@ -211,8 +217,8 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
//There is a temporary binding trace for an opportunity to resolve set method for array if needed (the initial trace should be used there)
|
||||
TemporaryTraceAndCache temporary = TemporaryTraceAndCache.create(
|
||||
contextWithExpectedType, "trace to resolve array set method for binary expression", expression);
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE)
|
||||
.replaceTraceAndCache(temporary);
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE)
|
||||
.replaceTraceAndCache(temporary).replaceContextDependency(INDEPENDENT);
|
||||
|
||||
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
||||
IElementType operationType = operationSign.getReferencedNameElementType();
|
||||
@@ -291,7 +297,8 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
|
||||
@NotNull
|
||||
protected JetTypeInfo visitAssignment(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceScope(scope);
|
||||
ExpressionTypingContext context =
|
||||
contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceScope(scope).replaceContextDependency(INDEPENDENT);
|
||||
JetExpression leftOperand = expression.getLeft();
|
||||
JetExpression left = leftOperand == null ? null : context.expressionTypingServices.deparenthesize(leftOperand, context);
|
||||
JetExpression right = expression.getRight();
|
||||
|
||||
+5
-3
@@ -35,6 +35,8 @@ import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.*;
|
||||
import static org.jetbrains.jet.lang.types.TypeUtils.*;
|
||||
import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.newWritableScopeImpl;
|
||||
|
||||
public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
@@ -44,7 +46,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
@Override
|
||||
public JetTypeInfo visitIsExpression(JetIsExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
|
||||
JetExpression leftHandSide = expression.getLeftHandSide();
|
||||
JetTypeInfo typeInfo = facade.safeGetTypeInfo(leftHandSide, context.replaceScope(context.scope));
|
||||
JetType knownType = typeInfo.getType();
|
||||
@@ -64,7 +66,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
public JetTypeInfo visitWhenExpression(JetWhenExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
|
||||
// TODO :change scope according to the bound value in the when header
|
||||
JetExpression subjectExpression = expression.getSubjectExpression();
|
||||
|
||||
@@ -304,7 +306,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
if (TypeUtils.isIntersectionEmpty(type, subjectType)) {
|
||||
if (isIntersectionEmpty(type, subjectType)) {
|
||||
context.trace.report(INCOMPATIBLE_TYPES.on(reportErrorOn, type, subjectType));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package h
|
||||
|
||||
trait A<T> {}
|
||||
|
||||
fun <T> newA(): A<T> = throw Exception()
|
||||
|
||||
trait Z
|
||||
|
||||
fun <T> id(t: T): T = t
|
||||
|
||||
//binary expressions
|
||||
//identifier
|
||||
fun <T> Z.foo(a: A<T>): A<T> = a
|
||||
|
||||
fun test(z: Z) {
|
||||
z <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!> <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>newA<!>()
|
||||
val a: A<Int> = id(z foo newA())
|
||||
val b: A<Int> = id(z.foo(newA()))
|
||||
use(a, b)
|
||||
}
|
||||
|
||||
//binary operation expression
|
||||
fun <T> Z.plus(a: A<T>): A<T> = a
|
||||
|
||||
fun test1(z: Z) {
|
||||
id(z <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>+<!> <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>newA<!>())
|
||||
val a: A<Z> = z + newA()
|
||||
val b: A<Z> = z.plus(newA())
|
||||
val c: A<Z> = id(z + newA())
|
||||
val d: A<Z> = id(z.plus(newA()))
|
||||
use(a, b, c, d)
|
||||
}
|
||||
|
||||
//comparison operation
|
||||
fun <T> Z.compareTo(a: A<T>): Int { use(a); return 1 }
|
||||
|
||||
fun test2(z: Z) {
|
||||
val a: Boolean = id(z <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!><<!> <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>newA<!>())
|
||||
val b: Boolean = id(z < newA<Z>())
|
||||
use(a, b)
|
||||
}
|
||||
|
||||
//'equals' operation
|
||||
fun Z.equals(any: Any): Int { use(any); return 1 }
|
||||
|
||||
fun test3(z: Z) {
|
||||
z == <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>newA<!>()
|
||||
z == newA<Z>()
|
||||
id(z == <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>newA<!>())
|
||||
id(z == newA<Z>())
|
||||
|
||||
id(z === <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>newA<!>())
|
||||
id(z === newA<Z>())
|
||||
}
|
||||
|
||||
//'in' operation
|
||||
fun test4(collection: Collection<A<*>>) {
|
||||
id(<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>newA<!>() in collection)
|
||||
id(newA<Int>() in collection)
|
||||
}
|
||||
|
||||
//boolean operations
|
||||
fun <T> toBeOrNot(): Boolean = throw Exception()
|
||||
|
||||
fun test5() {
|
||||
if (<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>toBeOrNot<!>() && <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>toBeOrNot<!>()) {}
|
||||
if (toBeOrNot<Int>() && toBeOrNot<Int>()) {}
|
||||
}
|
||||
|
||||
//use
|
||||
fun use(vararg a: Any?) = a
|
||||
@@ -2831,6 +2831,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
||||
doTest("compiler/testData/diagnostics/tests/inference/nestedCalls/arrayAccess.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("binaryExpressions.kt")
|
||||
public void testBinaryExpressions() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/inference/nestedCalls/binaryExpressions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("checkTypesForQualifiedProperties.kt")
|
||||
public void testCheckTypesForQualifiedProperties() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/inference/nestedCalls/checkTypesForQualifiedProperties.kt");
|
||||
|
||||
Reference in New Issue
Block a user