By Pavel Talanov: KT-618 overloaded assignment operators should not allow for returning types other than Unit of Subtypes or the type where they are defined
This commit is contained in:
+22
-3
@@ -20,11 +20,12 @@ import org.jetbrains.jet.lexer.JetTokens;
|
|||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
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.INDEXED_LVALUE_SET;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.BindingContext.VARIABLE_REASSIGNMENT;
|
||||||
import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.getExpressionReceiver;
|
import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.getExpressionReceiver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingVisitor {
|
public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingVisitor {
|
||||||
private final WritableScope scope;
|
private final WritableScope scope;
|
||||||
|
|
||||||
@@ -138,17 +139,35 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
|
|||||||
}
|
}
|
||||||
assignmentOperationType = getTypeForBinaryCall(scope, counterpartName, context, expression);
|
assignmentOperationType = getTypeForBinaryCall(scope, counterpartName, context, expression);
|
||||||
if (assignmentOperationType != null) {
|
if (assignmentOperationType != null) {
|
||||||
context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
|
context.trace.record(VARIABLE_REASSIGNMENT, expression);
|
||||||
ExpressionTypingUtils.checkWrappingInRef(expression.getLeft(), context);
|
ExpressionTypingUtils.checkWrappingInRef(expression.getLeft(), context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
temporaryBindingTrace.commit();
|
temporaryBindingTrace.commit();
|
||||||
|
checkReassignment(expression, context, assignmentOperationType, left);
|
||||||
}
|
}
|
||||||
checkLValue(context.trace, expression.getLeft());
|
checkLValue(context.trace, expression.getLeft());
|
||||||
return checkAssignmentType(assignmentOperationType, expression, contextWithExpectedType);
|
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
|
@Override
|
||||||
protected JetType visitAssignment(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
protected JetType visitAssignment(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceExpectedReturnType(TypeUtils.NO_EXPECTED_TYPE);
|
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceExpectedReturnType(TypeUtils.NO_EXPECTED_TYPE);
|
||||||
|
|||||||
@@ -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<String>) {
|
||||||
|
var c = B()
|
||||||
|
<!TYPE_MISMATCH!>c += B()<!>
|
||||||
|
<!TYPE_MISMATCH!>c *= B()<!>
|
||||||
|
<!TYPE_MISMATCH!>c /= B()<!>
|
||||||
|
<!TYPE_MISMATCH!>c -= B()<!>
|
||||||
|
<!TYPE_MISMATCH!>c %= B()<!>
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user