KT-5488 Invalid ambiguity between plus and plusAssign

#KT-5488  Fixed
This commit is contained in:
Andrey Breslav
2015-02-27 16:23:34 +03:00
parent 9c2a9e0bdb
commit 4c84b19b33
11 changed files with 170 additions and 18 deletions
@@ -837,33 +837,43 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
return !context.dataFlowInfo.getNullability(dataFlowValue).canBeNull();
}
public static void checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expression) {
checkLValue(trace, expression, false);
/**
* @return {@code true} iff expression can be assigned to
*/
public static boolean checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expression) {
return checkLValue(trace, expression, false);
}
private static void checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expressionWithParenthesis, boolean canBeThis) {
private static boolean checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expressionWithParenthesis, boolean canBeThis) {
JetExpression expression = JetPsiUtil.deparenthesize(expressionWithParenthesis);
if (expression instanceof JetArrayAccessExpression) {
JetExpression arrayExpression = ((JetArrayAccessExpression) expression).getArrayExpression();
if (arrayExpression != null) {
checkLValue(trace, arrayExpression, true);
}
return;
if (arrayExpression == null) return false;
return checkLValue(trace, arrayExpression, true);
}
if (canBeThis && expression instanceof JetThisExpression) return;
if (canBeThis && expression instanceof JetThisExpression) return true;
VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), expression, true);
boolean result = true;
JetExpression reportOn = expression != null ? expression : expressionWithParenthesis;
if (variable instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variable;
if (propertyDescriptor.isSetterProjectedOut()) {
trace.report(SETTER_PROJECTED_OUT.on(reportOn, propertyDescriptor));
result = false;
}
}
if (variable == null) {
trace.report(VARIABLE_EXPECTED.on(reportOn));
result = false;
}
else if (!variable.isVar()) {
result = false;
}
return result;
}
@Override
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.resolve.TemporaryBindingTrace;
import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
@@ -276,15 +277,24 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
JetType assignmentOperationType = OverloadResolutionResultsUtil.getResultingType(assignmentOperationDescriptors,
context.contextDependency);
// Check for '+'
Name counterpartName = OperatorConventions.BINARY_OPERATION_NAMES.get(OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType));
OverloadResolutionResults<FunctionDescriptor> binaryOperationDescriptors;
JetType binaryOperationType;
TemporaryTraceAndCache temporaryForBinaryOperation = TemporaryTraceAndCache.create(
context, "trace to check binary operation like '+' for", expression);
OverloadResolutionResults<FunctionDescriptor> binaryOperationDescriptors = components.callResolver.resolveBinaryCall(
context.replaceTraceAndCache(temporaryForBinaryOperation).replaceScope(scope),
receiver, expression, counterpartName
);
JetType binaryOperationType = OverloadResolutionResultsUtil.getResultingType(binaryOperationDescriptors, context.contextDependency);
boolean lhsAssignable = BasicExpressionTypingVisitor.checkLValue(TemporaryBindingTrace.create(context.trace, "Trace for checking assignability"), left);
if (assignmentOperationType == null || lhsAssignable) {
// Check for '+'
Name counterpartName = OperatorConventions.BINARY_OPERATION_NAMES.get(OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType));
binaryOperationDescriptors = components.callResolver.resolveBinaryCall(
context.replaceTraceAndCache(temporaryForBinaryOperation).replaceScope(scope),
receiver, expression, counterpartName
);
binaryOperationType = OverloadResolutionResultsUtil.getResultingType(binaryOperationDescriptors, context.contextDependency);
}
else {
binaryOperationDescriptors = OverloadResolutionResultsImpl.nameNotFound();
binaryOperationType = null;
}
JetType type = assignmentOperationType != null ? assignmentOperationType : binaryOperationType;
if (assignmentOperationDescriptors.isSuccess() && binaryOperationDescriptors.isSuccess()) {