提交 6251b413 编写于 作者: S svtk

New check rules for inc, plus & plusAssign

KT-1176 arrayList[0]++. Setter is stored for array access expression when it's needed
上级 db07a33d
......@@ -556,7 +556,7 @@ public abstract class StackValue {
}
public int receiverSize() {
if(isStandardStack(resolvedGetCall) && isStandardStack(resolvedSetCall)) {
if(isStandardStack(resolvedGetCall, 1) && isStandardStack(resolvedSetCall, 2)) {
return 2;
}
else {
......@@ -566,7 +566,7 @@ public abstract class StackValue {
@Override
public void dupReceiver(InstructionAdapter v) {
if(isStandardStack(resolvedGetCall) && isStandardStack(resolvedSetCall)) {
if(isStandardStack(resolvedGetCall, 1) && isStandardStack(resolvedSetCall, 2)) {
v.dup2(); // collection and index
}
else {
......@@ -702,7 +702,7 @@ public abstract class StackValue {
}
}
private boolean isStandardStack(ResolvedCall call) {
private boolean isStandardStack(ResolvedCall call, int valueParamsSize) {
if(call == null)
return true;
......@@ -710,13 +710,16 @@ public abstract class StackValue {
if(typeParameterDescriptor.isReified())
return false;
}
if(call.getResultingDescriptor().getValueParameters().size() != 1)
return false;
if(codegen.typeMapper.mapType(call.getResultingDescriptor().getValueParameters().get(0).getOutType()).getSize() != 1)
List<ValueParameterDescriptor> valueParameters = call.getResultingDescriptor().getValueParameters();
if(valueParameters.size() != valueParamsSize)
return false;
for (ValueParameterDescriptor valueParameter : valueParameters) {
if (codegen.typeMapper.mapType(valueParameter.getOutType()).getSize() != 1)
return false;
}
if(call.getThisObject().exists()) {
if(call.getReceiverArgument().exists())
return false;
......
......@@ -310,6 +310,16 @@ public class JetFlowInformationProvider {
hasReassignMethodReturningUnit = true;
}
}
if (descriptor == null) {
Collection<? extends DeclarationDescriptor> descriptors = trace.get(BindingContext.AMBIGUOUS_REFERENCE_TARGET, operationReference);
if (descriptors != null) {
for (DeclarationDescriptor referenceDescriptor : descriptors) {
if (JetStandardClasses.isUnit(((FunctionDescriptor) referenceDescriptor).getReturnType())) {
hasReassignMethodReturningUnit = true;
}
}
}
}
}
if (!hasReassignMethodReturningUnit) {
trace.report(Errors.VAL_REASSIGNMENT.on(expression, variableDescriptor));
......
......@@ -199,6 +199,15 @@ public interface Errors {
SimpleDiagnosticFactory NO_GET_METHOD = SimpleDiagnosticFactory.create(ERROR, "No get method providing array access");
SimpleDiagnosticFactory NO_SET_METHOD = SimpleDiagnosticFactory.create(ERROR, "No set method providing array access");
SimpleDiagnosticFactory INC_DEC_SHOULD_NOT_RETURN_UNIT = SimpleDiagnosticFactory.create(ERROR, "Functions inc(), dec() shouldn't return Unit to be used by operators ++, --");
ParameterizedDiagnosticFactory2<DeclarationDescriptor, JetSimpleNameExpression> ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT = new ParameterizedDiagnosticFactory2<DeclarationDescriptor, JetSimpleNameExpression>(ERROR, "Function ''{0}'' should return Unit to be used by corresponding operator ''{1}''", NAME) {
@Override
protected String makeMessageForB(@NotNull JetSimpleNameExpression expression) {
return expression.getText();
}
};
AmbiguousDescriptorDiagnosticFactory ASSIGN_OPERATOR_AMBIGUITY = AmbiguousDescriptorDiagnosticFactory.create("Assignment operators ambiguity: {0}");
SimpleDiagnosticFactory EQUALS_MISSING = SimpleDiagnosticFactory.create(ERROR, "No method 'equals(Any?) : Boolean' available");
SimpleDiagnosticFactory ASSIGNMENT_IN_EXPRESSION_CONTEXT = SimpleDiagnosticFactory.create(ERROR, "Assignments are not expressions, and only expressions are allowed in this context");
SimpleDiagnosticFactory NAMESPACE_IS_NOT_AN_EXPRESSION = SimpleDiagnosticFactory.create(ERROR, "'namespace' is not an expression, it can only be used on the left-hand side of a dot ('.')");
......
package org.jetbrains.jet.lang.resolve.calls;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collection;
/**
* @author svtk
*/
public class OverloadResolutionResultsUtil {
@NotNull
public static <D extends CallableDescriptor> OverloadResolutionResults<D> ambiguity(OverloadResolutionResults<D> results1, OverloadResolutionResults<D> results2) {
Collection<ResolvedCallImpl<D>> resultingCalls = Lists.newArrayList();
resultingCalls.addAll((Collection<ResolvedCallImpl<D>>) results1.getResultingCalls());
resultingCalls.addAll((Collection<ResolvedCallImpl<D>>) results2.getResultingCalls());
return OverloadResolutionResultsImpl.ambiguity(resultingCalls);
}
@Nullable
public static <D extends CallableDescriptor> JetType getResultType(OverloadResolutionResults<D> results) {
if (results.isSuccess()) {
return results.getResultingDescriptor().getReturnType();
}
return null;
}
}
......@@ -14,6 +14,7 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.CallMaker;
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResultsUtil;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.constants.*;
import org.jetbrains.jet.lang.resolve.constants.StringValue;
......@@ -27,6 +28,7 @@ import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lexer.JetTokens;
import javax.naming.ldap.ExtendedResponse;
import java.util.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
......@@ -661,24 +663,19 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression"));
return null;
}
JetType type = null;
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace);
BindingTrace initialTrace = context.trace;
context = context.replaceBindingTrace(temporaryTrace);
JetType type = facade.getType(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
if (type == null) {
temporaryTrace.commit();
return null;
}
if ((operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) && baseExpression instanceof JetArrayAccessExpression) {
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace);
JetType expressionType = facade.getType(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceBindingTrace(temporaryTrace));
if (expressionType != null) {
JetExpression stubExpression = ExpressionTypingUtils.createStubExpressionOfNecessaryType(baseExpression.getProject(), expressionType, context.trace);
type = resolveArrayAccessToLValue((JetArrayAccessExpression) baseExpression, stubExpression, context, true);
}
else {
temporaryTrace.commit();
context.trace.report(UNRESOLVED_REFERENCE.on(operationSign));
}
}
else {
type = facade.getType(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
JetExpression stubExpression = ExpressionTypingUtils.createStubExpressionOfNecessaryType(baseExpression.getProject(), type, context.trace);
resolveArrayAccessSetMethod((JetArrayAccessExpression) baseExpression, stubExpression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceBindingTrace(TemporaryBindingTrace.create(initialTrace)), context.trace);
}
if (type == null) return null;
ExpressionReceiver receiver = new ExpressionReceiver(baseExpression, type);
......@@ -687,12 +684,16 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
expression.getOperationReference(),
name);
if (!functionDescriptor.isSuccess()) return null;
if (!functionDescriptor.isSuccess()) {
temporaryTrace.commit();
return null;
}
JetType returnType = functionDescriptor.getResultingDescriptor().getReturnType();
JetType result;
if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) {
if (context.semanticServices.getTypeChecker().isSubtypeOf(returnType, JetStandardClasses.getUnitType())) {
result = JetStandardClasses.getUnitType();
context.trace.report(INC_DEC_SHOULD_NOT_RETURN_UNIT.on(operationSign));
}
else {
JetType receiverType = receiver.getType();
......@@ -712,7 +713,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
else {
result = returnType;
}
temporaryTrace.commit();
return DataFlowUtils.checkType(result, expression, context);
}
......@@ -849,13 +850,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
public boolean checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @Nullable JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context) {
String name = "contains";
ExpressionReceiver receiver = safeGetExpressionReceiver(facade, right, context.replaceExpectedType(NO_EXPECTED_TYPE));
OverloadResolutionResults<FunctionDescriptor> functionDescriptor = context.resolveCallWithGivenNameToDescriptor(
OverloadResolutionResults<FunctionDescriptor> resolutionResult = context.resolveCallWithGivenNameToDescriptor(
CallMaker.makeCallWithExpressions(callElement, receiver, null, operationSign, Collections.singletonList(left)),
operationSign,
name);
JetType containsType = functionDescriptor.isSuccess() ? functionDescriptor.getResultingDescriptor().getReturnType() : null;
JetType containsType = OverloadResolutionResultsUtil.getResultType(resolutionResult);
ensureBooleanResult(operationSign, name, containsType, context);
return functionDescriptor.isSuccess();
return resolutionResult.isSuccess();
}
private void ensureNonemptyIntersectionOfOperandTypes(JetBinaryExpression expression, ExpressionTypingContext context) {
......@@ -892,38 +893,24 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
}
@Override
public JetType visitArrayAccessExpression(JetArrayAccessExpression expression, ExpressionTypingContext contextWithExpectedType) {
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
JetExpression arrayExpression = expression.getArrayExpression();
ExpressionReceiver receiver = getExpressionReceiver(facade, arrayExpression, context.replaceScope(context.scope));
if (receiver != null) {
OverloadResolutionResults<FunctionDescriptor> results = context.resolveCallWithGivenName(
CallMaker.makeCallWithExpressions(expression, receiver, null, expression, expression.getIndexExpressions()),
expression,
"get"
);
if (results.isSuccess()) {
context.trace.record(INDEXED_LVALUE_GET, expression, results.getResultingCall());
return DataFlowUtils.checkType(results.getResultingDescriptor().getReturnType(), expression, contextWithExpectedType);
}
}
context.trace.report(NO_GET_METHOD.on(expression.getIndicesNode()));
return null;
public JetType visitArrayAccessExpression(JetArrayAccessExpression expression, ExpressionTypingContext context) {
return resolveArrayAccessGetMethod(expression, context.replaceExpectedType(NO_EXPECTED_TYPE));
}
@Nullable
public JetType getTypeForBinaryCall(JetScope scope, String name, ExpressionTypingContext context, JetBinaryExpression binaryExpression) {
ExpressionReceiver receiver = safeGetExpressionReceiver(facade, binaryExpression.getLeft(), context.replaceScope(scope));
OverloadResolutionResults<FunctionDescriptor> results = context.replaceScope(scope).resolveCallWithGivenNameToDescriptor(
return OverloadResolutionResultsUtil.getResultType(getResolutionResultsForBinaryCall(scope, name, context, binaryExpression, receiver));
}
@NotNull
/*package*/ OverloadResolutionResults<FunctionDescriptor> getResolutionResultsForBinaryCall(JetScope scope, String name, ExpressionTypingContext context, JetBinaryExpression binaryExpression, ExpressionReceiver receiver) {
// ExpressionReceiver receiver = safeGetExpressionReceiver(facade, binaryExpression.getLeft(), context.replaceScope(scope));
return context.replaceScope(scope).resolveCallWithGivenNameToDescriptor(
CallMaker.makeCall(receiver, binaryExpression),
binaryExpression.getOperationReference(),
name
);
if (results.isSuccess()) {
return results.getResultingDescriptor().getReturnType();
}
return null;
}
@Override
......@@ -999,45 +986,38 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName()));
return null;
}
/*package*/ JetType resolveArrayAccessToLValue(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull JetExpression right, @NotNull ExpressionTypingContext context, final boolean getterNeeded) {
ExpressionReceiver receiver = getExpressionReceiver(facade, arrayAccessExpression.getArrayExpression(), context.replaceExpectedType(NO_EXPECTED_TYPE));
if (receiver == null) return null;
OverloadResolutionResults<FunctionDescriptor> getFunctionResults = null;
if (getterNeeded) {
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace);
getFunctionResults = context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceBindingTrace(temporaryTrace).resolveCallWithGivenName(
CallMaker.makeArrayGetCall(receiver, arrayAccessExpression),
arrayAccessExpression,
"get");
if (!getFunctionResults.isSuccess()) {
temporaryTrace.commit();
context.trace.report(NO_GET_METHOD.on(arrayAccessExpression.getIndicesNode()));
return null;
}
context.trace.record(INDEXED_LVALUE_GET, arrayAccessExpression, getFunctionResults.getResultingCall());
}
@Nullable
/*package*/ JetType resolveArrayAccessSetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull JetExpression rightHandSide, @NotNull ExpressionTypingContext context, @NotNull BindingTrace traceForResolveResult) {
return resolveArrayAccessSpecialMethod(arrayAccessExpression, rightHandSide, context, traceForResolveResult, false);
}
@Nullable
/*package*/ JetType resolveArrayAccessGetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull ExpressionTypingContext context) {
return resolveArrayAccessSpecialMethod(arrayAccessExpression, null, context, context.trace, true);
}
Call call = CallMaker.makeArraySetCall(receiver, arrayAccessExpression, right);
OverloadResolutionResults<FunctionDescriptor> setFunctionResults = context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName(
call,
@Nullable
private JetType resolveArrayAccessSpecialMethod(@NotNull JetArrayAccessExpression arrayAccessExpression,
@Nullable JetExpression rightHandSide, //only for 'set' method
@NotNull ExpressionTypingContext context,
@NotNull BindingTrace traceForResolveResult,
boolean isGet) {
JetType arrayType = facade.getType(arrayAccessExpression.getArrayExpression(), context);
if (arrayType == null) return null;
ExpressionReceiver receiver = new ExpressionReceiver(arrayAccessExpression.getArrayExpression(), arrayType);
if (!isGet) assert rightHandSide != null;
OverloadResolutionResults<FunctionDescriptor> functionResults = context.resolveCallWithGivenName(
isGet ? CallMaker.makeArrayGetCall(receiver, arrayAccessExpression) : CallMaker.makeArraySetCall(receiver, arrayAccessExpression, rightHandSide),
arrayAccessExpression,
"set");
if (!setFunctionResults.isSuccess()) {
context.trace.report(NO_SET_METHOD.on(arrayAccessExpression.getIndicesNode()));
if (getterNeeded) {
return getFunctionResults.getResultingDescriptor().getReturnType();
}
isGet ? "get" : "set");
if (!functionResults.isSuccess()) {
JetContainerNode indicesNode = arrayAccessExpression.getIndicesNode();
traceForResolveResult.report(isGet ? NO_GET_METHOD.on(indicesNode) : NO_SET_METHOD.on(indicesNode));
return null;
}
FunctionDescriptor setFunctionDescriptor = setFunctionResults.getResultingDescriptor();
context.trace.record(INDEXED_LVALUE_SET, arrayAccessExpression, setFunctionResults.getResultingCall());
if (getterNeeded) {
return getFunctionResults.getResultingDescriptor().getReturnType();
}
return setFunctionDescriptor.getReturnType();
traceForResolveResult.record(isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression, functionResults.getResultingCall());
return functionResults.getResultingDescriptor().getReturnType();
}
}
\ No newline at end of file
package org.jetbrains.jet.lang.types.expressions;
import com.google.common.collect.Sets;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResultsUtil;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lexer.JetTokens;
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.REFERENCE_TARGET;
import static org.jetbrains.jet.lang.resolve.BindingContext.VARIABLE_REASSIGNMENT;
/**
......@@ -140,63 +146,74 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
}
protected JetType visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceExpectedReturnType(TypeUtils.NO_EXPECTED_TYPE);
// If there's += (or similar op) defined as such, we just call it.
//There is a temporary binding trace for an opportunity to resolve set method for array if needed (the initial trace should be used there)
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(contextWithExpectedType.trace);
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceExpectedReturnType(TypeUtils.NO_EXPECTED_TYPE).replaceBindingTrace(temporaryBindingTrace);
JetSimpleNameExpression operationSign = expression.getOperationReference();
IElementType operationType = operationSign.getReferencedNameElementType();
String name = OperatorConventions.ASSIGNMENT_OPERATIONS.get(operationType);
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(context.trace);
JetType assignmentOperationType = basic.getTypeForBinaryCall(scope, name, context.replaceBindingTrace(temporaryBindingTrace), expression);
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
// If there isn't, we call plus (or like) and then assign
if (assignmentOperationType == null) {
String counterpartName = OperatorConventions.BINARY_OPERATION_NAMES.get(OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType));
if (left == null) return null;
if (left instanceof JetArrayAccessExpression) {
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
basic.resolveArrayAccessToLValue(arrayAccessExpression, expression.getRight(), context.replaceScope(scope), false);
}
assignmentOperationType = basic.getTypeForBinaryCall(scope, counterpartName, context, expression);
if (assignmentOperationType != null) {
context.trace.record(VARIABLE_REASSIGNMENT, expression);
ExpressionTypingUtils.checkWrappingInRef(expression.getLeft(), context);
}
}
else {
JetType leftType = facade.getType(left, context);
if (leftType == null) {
facade.getType(expression.getRight(), context);
context.trace.report(UNRESOLVED_REFERENCE.on(operationSign));
temporaryBindingTrace.commit();
checkReassignment(expression, context, assignmentOperationType, left);
return null;
}
basic.checkLValue(context.trace, expression.getLeft());
return checkAssignmentType(assignmentOperationType, expression, contextWithExpectedType);
}
private void checkReassignment(@NotNull JetBinaryExpression expression, @NotNull ExpressionTypingContext context,
@NotNull JetType assignmentOperationType, @Nullable JetExpression left) {
if (left == null) return;
JetType leftType = facade.getType(left, context.replaceScope(scope));
if (leftType == null) return;
boolean isUnit = context.semanticServices.getTypeChecker().
isSubtypeOf(assignmentOperationType, JetStandardClasses.getUnitType());
if (isUnit) return;
ExpressionReceiver receiver = new ExpressionReceiver(left, leftType);
if (context.semanticServices.getTypeChecker().isSubtypeOf(assignmentOperationType, leftType)) {
context.trace.record(VARIABLE_REASSIGNMENT, expression);
// We check that defined only one of '+=' and '+' operations, and call it (in the case '+' we then also assign)
// Check for '+='
String name = OperatorConventions.ASSIGNMENT_OPERATIONS.get(operationType);
TemporaryBindingTrace assignmentOperationTrace = TemporaryBindingTrace.create(context.trace);
OverloadResolutionResults<FunctionDescriptor> assignmentOperationDescriptors = basic.getResolutionResultsForBinaryCall(scope, name, context.replaceBindingTrace(assignmentOperationTrace), expression, receiver);
JetType assignmentOperationType = OverloadResolutionResultsUtil.getResultType(assignmentOperationDescriptors);
// Check for '+'
String counterpartName = OperatorConventions.BINARY_OPERATION_NAMES.get(OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType));
TemporaryBindingTrace binaryOperationTrace = TemporaryBindingTrace.create(context.trace);
OverloadResolutionResults<FunctionDescriptor> binaryOperationDescriptors = basic.getResolutionResultsForBinaryCall(scope, counterpartName, context.replaceBindingTrace(binaryOperationTrace), expression, receiver);
JetType binaryOperationType = OverloadResolutionResultsUtil.getResultType(binaryOperationDescriptors);
JetType type = assignmentOperationType != null ? assignmentOperationType : binaryOperationType;
if (assignmentOperationType != null && binaryOperationType != null) {
OverloadResolutionResults<FunctionDescriptor> ambiguityResolutionResults = OverloadResolutionResultsUtil.ambiguity(assignmentOperationDescriptors, binaryOperationDescriptors);
context.trace.report(ASSIGN_OPERATOR_AMBIGUITY.on(operationSign, ambiguityResolutionResults.getResultingCalls()));
Collection<DeclarationDescriptor> descriptors = Sets.newHashSet();
for (ResolvedCall<? extends FunctionDescriptor> call : ambiguityResolutionResults.getResultingCalls()) {
descriptors.add(call.getResultingDescriptor());
}
facade.getType(expression.getRight(), context);
context.trace.record(AMBIGUOUS_REFERENCE_TARGET, operationSign, descriptors);
}
else {
context.trace.report(TYPE_MISMATCH.on(expression, leftType, assignmentOperationType));
else if (assignmentOperationType != null) {
assignmentOperationTrace.commit();
if (!JetStandardClasses.isUnit(assignmentOperationType)) {
context.trace.report(ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT.on(operationSign, assignmentOperationDescriptors.getResultingDescriptor(), operationSign));
}
} else {
binaryOperationTrace.commit();
context.trace.record(VARIABLE_REASSIGNMENT, expression);
ExpressionTypingUtils.checkWrappingInRef(expression.getLeft(), context);
if (left instanceof JetArrayAccessExpression) {
ExpressionTypingContext contextForResolve = context.replaceScope(scope).replaceBindingTrace(TemporaryBindingTrace.create(contextWithExpectedType.trace));
basic.resolveArrayAccessSetMethod((JetArrayAccessExpression) left, expression.getRight(), contextForResolve, context.trace);
}
}
basic.checkLValue(context.trace, expression.getLeft());
temporaryBindingTrace.commit();
return checkAssignmentType(type, expression, contextWithExpectedType);
}
protected JetType visitAssignment(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceExpectedReturnType(TypeUtils.NO_EXPECTED_TYPE);
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
JetExpression right = expression.getRight();
if (left instanceof JetArrayAccessExpression) {
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
JetType assignmentType = basic.resolveArrayAccessToLValue(arrayAccessExpression, right, context.replaceScope(scope), false); //todo
JetType assignmentType = basic.resolveArrayAccessSetMethod(arrayAccessExpression, right, context.replaceScope(scope), context.trace);
basic.checkLValue(context.trace, arrayAccessExpression);
return checkAssignmentType(assignmentType, expression, contextWithExpectedType);
}
......
......@@ -7,7 +7,7 @@ class ArrayWrapper<T>() {
contents.add(item)
}
fun plusAssign(rhs: ArrayWrapper<T>): ArrayWrapper<T> {
fun plus(rhs: ArrayWrapper<T>): ArrayWrapper<T> {
val result = ArrayWrapper<T>()
result.contents.addAll(contents)
result.contents.addAll(rhs.contents)
......
......@@ -37,7 +37,7 @@ fun test4() : Boolean {
return true
}
/*fun test5() : Boolean {
fun test5() : Boolean {
var mnr = Array<MyNumber>(2,{MyNumber(42)})
mnr[0]++
if (mnr[0].i != 43) return false
......@@ -69,7 +69,7 @@ fun test8() : Boolean {
if (mnr[1].i != 42) return false
return true
}
*/
fun box() : String {
var m = MyNumber(42)
......@@ -78,7 +78,7 @@ fun box() : String {
if (!test2()) return "fail test 2"
if (!test3()) return "fail test 3"
if (!test4()) return "fail test 4"
/*
if (!test5()) return "fail test 5"
if (!test6()) return "fail test 6"
if (!test7()) return "fail test 7"
......@@ -86,11 +86,11 @@ fun box() : String {
++m
if (m.i != 44) return "fail 0"
if (m.i != 43) return "fail 0"
var m1 = ++m
if (m1.i != 46) return "fail 3"
if (m.i != 46) return "fail 4"
*/
if (m1.i != 44) return "fail 3"
if (m.i != 44) return "fail 4"
return "OK"
}
......@@ -35,12 +35,12 @@ class UnitIncDec() {
fun testUnitIncDec() {
var x = UnitIncDec()
x++
++x
x--
--x
x = <!TYPE_MISMATCH, UNUSED_CHANGED_VALUE!>x++<!>
x = <!TYPE_MISMATCH, UNUSED_CHANGED_VALUE!>x--<!>
x = <!TYPE_MISMATCH!>++x<!>
x = <!TYPE_MISMATCH, UNUSED_VALUE!>--x<!>
x<!INC_DEC_SHOULD_NOT_RETURN_UNIT!>++<!>
<!INC_DEC_SHOULD_NOT_RETURN_UNIT!>++<!>x
x<!INC_DEC_SHOULD_NOT_RETURN_UNIT!>--<!>
<!INC_DEC_SHOULD_NOT_RETURN_UNIT!>--<!>x
x = <!UNUSED_CHANGED_VALUE!>x<!INC_DEC_SHOULD_NOT_RETURN_UNIT!>++<!><!>
x = <!UNUSED_CHANGED_VALUE!>x<!INC_DEC_SHOULD_NOT_RETURN_UNIT!>--<!><!>
x = <!INC_DEC_SHOULD_NOT_RETURN_UNIT!>++<!>x
x = <!UNUSED_VALUE!><!INC_DEC_SHOULD_NOT_RETURN_UNIT!>--<!>x<!>
}
\ No newline at end of file
......@@ -20,9 +20,9 @@ class B() {
fun main(args : Array<String>) {
var c = B()
<!TYPE_MISMATCH!>c += B()<!>
<!TYPE_MISMATCH!>c *= B()<!>
<!TYPE_MISMATCH!>c /= B()<!>
<!TYPE_MISMATCH!>c -= B()<!>
<!TYPE_MISMATCH!>c %= B()<!>
c <!ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT!>+=<!> B()
c <!ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT!>*=<!> B()
c <!ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT!>/=<!> B()
c <!ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT!>-=<!> B()
c <!ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT!>%=<!> B()
}
\ No newline at end of file
......@@ -35,12 +35,12 @@ class UnitIncDec() {
fun testUnitIncDec() {
var x = UnitIncDec()
x++
++x
x--
--x
x = <error>x++</error>
x = <error>x--</error>
x = <error>++x</error>
x = <error>--x</error>
x<error>++</error>
<error>++</error>x
x<error>--</error>
<error>--</error>x
x = <warning>x<error>++</error></warning>
x = <warning>x<error>--</error></warning>
x = <error>++</error>x
x = <warning><error>--</error>x</warning>
}
\ No newline at end of file
......@@ -2,8 +2,6 @@ package std
import java.io.StringReader
inline fun <T> T?.plus(str: String?) : String { return toString() + str }
inline fun String.lastIndexOf(s: String) = (this as java.lang.String).lastIndexOf(s)
inline fun String.lastIndexOf(s: Char) = (this as java.lang.String).lastIndexOf(s.toString())
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册