use of org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo in project kotlin by JetBrains.
the class ExpressionTypingVisitorForStatements method visitAssignment.
@NotNull
protected KotlinTypeInfo visitAssignment(KtBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceScope(scope).replaceContextDependency(INDEPENDENT);
KtExpression leftOperand = expression.getLeft();
if (leftOperand instanceof KtAnnotatedExpression) {
basic.resolveAnnotationsOnExpression((KtAnnotatedExpression) leftOperand, context);
}
KtExpression left = deparenthesize(leftOperand);
KtExpression right = expression.getRight();
if (left instanceof KtArrayAccessExpression) {
KtArrayAccessExpression arrayAccessExpression = (KtArrayAccessExpression) left;
if (right == null)
return TypeInfoFactoryKt.noTypeInfo(context);
KotlinTypeInfo typeInfo = basic.resolveArrayAccessSetMethod(arrayAccessExpression, right, context, context.trace);
basic.checkLValue(context.trace, context, arrayAccessExpression, right, expression);
return typeInfo.replaceType(checkAssignmentType(typeInfo.getType(), expression, contextWithExpectedType));
}
KotlinTypeInfo leftInfo = ExpressionTypingUtils.getTypeInfoOrNullType(left, context, facade);
KotlinType expectedType = refineTypeFromPropertySetterIfPossible(context.trace.getBindingContext(), leftOperand, leftInfo.getType());
DataFlowInfo dataFlowInfo = leftInfo.getDataFlowInfo();
KotlinTypeInfo resultInfo;
if (right != null) {
resultInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo).replaceExpectedType(expectedType).replaceCallPosition(new CallPosition.PropertyAssignment(leftOperand)));
dataFlowInfo = resultInfo.getDataFlowInfo();
KotlinType rightType = resultInfo.getType();
if (left != null && expectedType != null && rightType != null) {
DataFlowValue leftValue = DataFlowValueFactory.createDataFlowValue(left, expectedType, context);
DataFlowValue rightValue = DataFlowValueFactory.createDataFlowValue(right, rightType, context);
// We cannot say here anything new about rightValue except it has the same value as leftValue
resultInfo = resultInfo.replaceDataFlowInfo(dataFlowInfo.assign(leftValue, rightValue, components.languageVersionSettings));
}
} else {
resultInfo = leftInfo;
}
if (expectedType != null && leftOperand != null) {
//if expectedType == null, some other error has been generated
basic.checkLValue(context.trace, context, leftOperand, right, expression);
}
return resultInfo.replaceType(components.dataFlowAnalyzer.checkStatementType(expression, contextWithExpectedType));
}
use of org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo in project kotlin by JetBrains.
the class BodyResolver method resolveFunctionBody.
private void resolveFunctionBody(@NotNull DataFlowInfo outerDataFlowInfo, @NotNull BindingTrace trace, @NotNull KtDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor, @NotNull LexicalScope scope, @Nullable Function1<LexicalScope, DataFlowInfo> beforeBlockBody, // Creates wrapper scope for header resolution if necessary (see resolveSecondaryConstructorBody)
@Nullable Function1<LexicalScope, LexicalScope> headerScopeFactory) {
PreliminaryDeclarationVisitor.Companion.createForDeclaration(function, trace);
LexicalScope innerScope = FunctionDescriptorUtil.getFunctionInnerScope(scope, functionDescriptor, trace, overloadChecker);
List<KtParameter> valueParameters = function.getValueParameters();
List<ValueParameterDescriptor> valueParameterDescriptors = functionDescriptor.getValueParameters();
LexicalScope headerScope = headerScopeFactory != null ? headerScopeFactory.invoke(innerScope) : innerScope;
valueParameterResolver.resolveValueParameters(valueParameters, valueParameterDescriptors, headerScope, outerDataFlowInfo, trace);
// Synthetic "field" creation
if (functionDescriptor instanceof PropertyAccessorDescriptor && functionDescriptor.getExtensionReceiverParameter() == null) {
PropertyAccessorDescriptor accessorDescriptor = (PropertyAccessorDescriptor) functionDescriptor;
KtProperty property = (KtProperty) function.getParent();
final SyntheticFieldDescriptor fieldDescriptor = new SyntheticFieldDescriptor(accessorDescriptor, property);
innerScope = new LexicalScopeImpl(innerScope, functionDescriptor, true, null, LexicalScopeKind.PROPERTY_ACCESSOR_BODY, LocalRedeclarationChecker.DO_NOTHING.INSTANCE, new Function1<LexicalScopeImpl.InitializeHandler, Unit>() {
@Override
public Unit invoke(LexicalScopeImpl.InitializeHandler handler) {
handler.addVariableDescriptor(fieldDescriptor);
return Unit.INSTANCE;
}
});
// Check parameter name shadowing
for (KtParameter parameter : function.getValueParameters()) {
if (SyntheticFieldDescriptor.NAME.equals(parameter.getNameAsName())) {
trace.report(Errors.ACCESSOR_PARAMETER_NAME_SHADOWING.on(parameter));
}
}
}
DataFlowInfo dataFlowInfo = null;
if (beforeBlockBody != null) {
dataFlowInfo = beforeBlockBody.invoke(headerScope);
}
if (function.hasBody()) {
expressionTypingServices.checkFunctionReturnType(innerScope, function, functionDescriptor, dataFlowInfo != null ? dataFlowInfo : outerDataFlowInfo, null, trace);
}
assert functionDescriptor.getReturnType() != null;
}
use of org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo in project kotlin by JetBrains.
the class BasicExpressionTypingVisitor method visitBooleanOperationExpression.
@NotNull
private KotlinTypeInfo visitBooleanOperationExpression(@Nullable IElementType operationType, @Nullable KtExpression left, @Nullable KtExpression right, @NotNull ExpressionTypingContext context) {
KotlinType booleanType = components.builtIns.getBooleanType();
KotlinTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context.replaceExpectedType(booleanType), facade);
DataFlowInfo dataFlowInfo = leftTypeInfo.getDataFlowInfo();
LexicalWritableScope leftScope = newWritableScopeImpl(context, LexicalScopeKind.LEFT_BOOLEAN_EXPRESSION, facade.getComponents().overloadChecker);
// TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition
boolean isAnd = operationType == KtTokens.ANDAND;
DataFlowInfo flowInfoLeft = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(left, isAnd, context).and(dataFlowInfo);
LexicalWritableScope rightScope = isAnd ? leftScope : newWritableScopeImpl(context, LexicalScopeKind.RIGHT_BOOLEAN_EXPRESSION, facade.getComponents().overloadChecker);
ExpressionTypingContext contextForRightExpr = context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope).replaceExpectedType(booleanType);
if (right != null) {
facade.getTypeInfo(right, contextForRightExpr);
}
return leftTypeInfo.replaceType(booleanType);
}
use of org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo in project kotlin by JetBrains.
the class BasicExpressionTypingVisitor method visitElvisExpression.
@NotNull
private KotlinTypeInfo visitElvisExpression(@NotNull KtBinaryExpression expression, @NotNull ExpressionTypingContext contextWithExpectedType) {
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
KtExpression left = expression.getLeft();
KtExpression right = expression.getRight();
if (left == null || right == null) {
getTypeInfoOrNullType(left, context, facade);
return TypeInfoFactoryKt.noTypeInfo(context);
}
Call call = createCallForSpecialConstruction(expression, expression.getOperationReference(), Lists.newArrayList(left, right));
ResolvedCall<FunctionDescriptor> resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(call, ResolveConstruct.ELVIS, Lists.newArrayList("left", "right"), Lists.newArrayList(true, false), contextWithExpectedType, null);
KotlinTypeInfo leftTypeInfo = BindingContextUtils.getRecordedTypeInfo(left, context.trace.getBindingContext());
if (ArgumentTypeResolver.isFunctionLiteralArgument(left, context)) {
context.trace.report(USELESS_ELVIS_ON_LAMBDA_EXPRESSION.on(expression.getOperationReference()));
if (leftTypeInfo == null)
return TypeInfoFactoryKt.noTypeInfo(context);
}
assert leftTypeInfo != null : "Left expression was not processed: " + expression;
KotlinType leftType = leftTypeInfo.getType();
if (leftType != null && isKnownToBeNotNull(left, leftType, context)) {
context.trace.report(USELESS_ELVIS.on(expression, leftType));
} else if (KtPsiUtil.isNullConstant(right) && leftType != null && !FlexibleTypesKt.isNullabilityFlexible(leftType)) {
context.trace.report(USELESS_ELVIS_RIGHT_IS_NULL.on(expression));
}
KotlinTypeInfo rightTypeInfo = BindingContextUtils.getRecordedTypeInfo(right, context.trace.getBindingContext());
if (rightTypeInfo == null && ArgumentTypeResolver.isFunctionLiteralArgument(right, context)) {
// the type is computed later in call completer according to the '?:' semantics as a function
return TypeInfoFactoryKt.noTypeInfo(context);
}
assert rightTypeInfo != null : "Right expression was not processed: " + expression;
boolean loopBreakContinuePossible = leftTypeInfo.getJumpOutPossible() || rightTypeInfo.getJumpOutPossible();
KotlinType rightType = rightTypeInfo.getType();
// Only left argument DFA is taken into account here: we cannot be sure that right argument is joined
// (we merge it with right DFA if right argument contains no jump outside)
DataFlowInfo dataFlowInfo = resolvedCall.getDataFlowInfoForArguments().getInfo(call.getValueArguments().get(1));
KotlinType type = resolvedCall.getResultingDescriptor().getReturnType();
if (type == null || rightType == null || leftType == null && KotlinBuiltIns.isNothing(rightType))
return TypeInfoFactoryKt.noTypeInfo(dataFlowInfo);
if (leftType != null) {
DataFlowValue leftValue = createDataFlowValue(left, leftType, context);
DataFlowInfo rightDataFlowInfo = resolvedCall.getDataFlowInfoForArguments().getResultInfo();
boolean jumpInRight = KotlinBuiltIns.isNothing(rightType);
DataFlowValue nullValue = DataFlowValue.nullValue(components.builtIns);
// left argument is considered not-null if it's not-null also in right part or if we have jump in right part
if (jumpInRight || !rightDataFlowInfo.getStableNullability(leftValue).canBeNull()) {
dataFlowInfo = dataFlowInfo.disequate(leftValue, nullValue, components.languageVersionSettings);
if (left instanceof KtBinaryExpressionWithTypeRHS) {
dataFlowInfo = establishSubtypingForTypeRHS((KtBinaryExpressionWithTypeRHS) left, dataFlowInfo, context, components.languageVersionSettings);
}
}
DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(expression, type, context);
dataFlowInfo = dataFlowInfo.assign(resultValue, leftValue, components.languageVersionSettings).disequate(resultValue, nullValue, components.languageVersionSettings);
if (!jumpInRight) {
DataFlowValue rightValue = DataFlowValueFactory.createDataFlowValue(right, rightType, context);
rightDataFlowInfo = rightDataFlowInfo.assign(resultValue, rightValue, components.languageVersionSettings);
dataFlowInfo = dataFlowInfo.or(rightDataFlowInfo);
}
}
// but result is not nullable if the right type is not nullable
if (!TypeUtils.isNullableType(rightType) && TypeUtils.isNullableType(type)) {
type = TypeUtils.makeNotNullable(type);
}
if (context.contextDependency == DEPENDENT) {
return TypeInfoFactoryKt.createTypeInfo(type, dataFlowInfo);
}
// If break or continue was possible, take condition check info as the jump info
return TypeInfoFactoryKt.createTypeInfo(components.dataFlowAnalyzer.checkType(type, expression, contextWithExpectedType), dataFlowInfo, loopBreakContinuePossible, context.dataFlowInfo);
}
use of org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo in project kotlin by JetBrains.
the class BasicExpressionTypingVisitor method visitEquality.
private KotlinTypeInfo visitEquality(KtBinaryExpression expression, ExpressionTypingContext context, KtSimpleNameExpression operationSign, final KtExpression left, final KtExpression right) {
if (right == null || left == null) {
ExpressionTypingUtils.getTypeInfoOrNullType(right, context, facade);
ExpressionTypingUtils.getTypeInfoOrNullType(left, context, facade);
return TypeInfoFactoryKt.createTypeInfo(components.builtIns.getBooleanType(), context);
}
KotlinTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context, facade);
DataFlowInfo dataFlowInfo = leftTypeInfo.getDataFlowInfo();
ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
KotlinTypeInfo rightTypeInfo = facade.getTypeInfo(right, contextWithDataFlow);
TemporaryBindingTrace traceInterpretingRightAsNullableAny = TemporaryBindingTrace.create(context.trace, "trace to resolve 'equals(Any?)' interpreting as of type Any? an expression:", right);
traceInterpretingRightAsNullableAny.recordType(right, components.builtIns.getNullableAnyType());
// Nothing? has no members, and `equals()` would be unresolved on it
KotlinType leftType = leftTypeInfo.getType();
if (leftType != null && KotlinBuiltIns.isNothingOrNullableNothing(leftType)) {
traceInterpretingRightAsNullableAny.recordType(left, components.builtIns.getNullableAnyType());
}
ExpressionTypingContext newContext = context.replaceBindingTrace(traceInterpretingRightAsNullableAny);
ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, newContext);
Call call = CallMaker.makeCallWithExpressions(expression, receiver, // semantically, a call to `==` is a safe call
new KtPsiFactory(expression.getProject()).createSafeCallNode(), operationSign, Collections.singletonList(right));
OverloadResolutionResults<FunctionDescriptor> resolutionResults = components.callResolver.resolveCallWithGivenName(newContext, call, operationSign, OperatorNameConventions.EQUALS);
traceInterpretingRightAsNullableAny.commit(new TraceEntryFilter() {
@Override
public boolean accept(@Nullable WritableSlice<?, ?> slice, Object key) {
// the type of the right (and sometimes left) expression isn't 'Any?' actually
if ((key == right || key == left) && slice == EXPRESSION_TYPE_INFO)
return false;
return true;
}
}, true);
if (resolutionResults.isSuccess()) {
FunctionDescriptor equals = resolutionResults.getResultingCall().getResultingDescriptor();
if (ensureBooleanResult(operationSign, OperatorNameConventions.EQUALS, equals.getReturnType(), context)) {
ensureNonemptyIntersectionOfOperandTypes(expression, context);
}
} else {
if (resolutionResults.isAmbiguity()) {
context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResults.getResultingCalls()));
} else {
context.trace.report(EQUALS_MISSING.on(operationSign));
}
}
return rightTypeInfo.replaceType(components.builtIns.getBooleanType());
}
Aggregations