analyze a lot of expressions in independent of context (expected type) mode

This commit is contained in:
Svetlana Isakova
2013-08-09 18:40:26 +04:00
parent fbd94a9507
commit dc51a2d238
10 changed files with 183 additions and 64 deletions
@@ -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);
}
};
@@ -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;
@@ -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());
@@ -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);
}
@@ -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();
@@ -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");