diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java index 68704d336ee..7ed8e8e7c12 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java @@ -20,11 +20,12 @@ import org.jetbrains.jet.lexer.JetTokens; import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.resolve.BindingContext.INDEXED_LVALUE_SET; +import static org.jetbrains.jet.lang.resolve.BindingContext.VARIABLE_REASSIGNMENT; import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.getExpressionReceiver; /** -* @author abreslav -*/ + * @author abreslav + */ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingVisitor { private final WritableScope scope; @@ -138,17 +139,35 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV } assignmentOperationType = getTypeForBinaryCall(scope, counterpartName, context, expression); if (assignmentOperationType != null) { - context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression); + context.trace.record(VARIABLE_REASSIGNMENT, expression); ExpressionTypingUtils.checkWrappingInRef(expression.getLeft(), context); } } else { temporaryBindingTrace.commit(); + checkReassignment(expression, context, assignmentOperationType, left); } 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; + + if (context.semanticServices.getTypeChecker().isSubtypeOf(assignmentOperationType, leftType)) { + context.trace.record(VARIABLE_REASSIGNMENT, expression); + } + else { + context.trace.report(TYPE_MISMATCH.on(expression, leftType, assignmentOperationType)); + } + } + @Override protected JetType visitAssignment(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) { ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceExpectedReturnType(TypeUtils.NO_EXPECTED_TYPE); diff --git a/compiler/testData/checkerWithErrorTypes/quick/regressions/kt618.jet b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt618.jet new file mode 100644 index 00000000000..569d286c17b --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt618.jet @@ -0,0 +1,28 @@ +namespace lol + +class B() { + fun plusAssign(other : B) : String { + return "s" + } + fun minusAssign(other : B) : String { + return "s" + } + fun modAssign(other : B) : String { + return "s" + } + fun divAssign(other : B) : String { + return "s" + } + fun timesAssign(other : B) : String { + return "s" + } +} + +fun main(args : Array) { + var c = B() + c += B() + c *= B() + c /= B() + c -= B() + c %= B() +}