Allow to call += on a val
This commit is contained in:
+4
-1
@@ -238,6 +238,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
|
|
||||||
JetType type = assignmentOperationType != null ? assignmentOperationType : binaryOperationType;
|
JetType type = assignmentOperationType != null ? assignmentOperationType : binaryOperationType;
|
||||||
if (assignmentOperationType != null && binaryOperationType != null) {
|
if (assignmentOperationType != null && binaryOperationType != null) {
|
||||||
|
// Both 'plus()' and 'plusAssign()' available => ambiguity
|
||||||
OverloadResolutionResults<FunctionDescriptor> ambiguityResolutionResults = OverloadResolutionResultsUtil.ambiguity(assignmentOperationDescriptors, binaryOperationDescriptors);
|
OverloadResolutionResults<FunctionDescriptor> ambiguityResolutionResults = OverloadResolutionResultsUtil.ambiguity(assignmentOperationDescriptors, binaryOperationDescriptors);
|
||||||
context.trace.report(ASSIGN_OPERATOR_AMBIGUITY.on(operationSign, ambiguityResolutionResults.getResultingCalls()));
|
context.trace.report(ASSIGN_OPERATOR_AMBIGUITY.on(operationSign, ambiguityResolutionResults.getResultingCalls()));
|
||||||
Collection<DeclarationDescriptor> descriptors = Sets.newHashSet();
|
Collection<DeclarationDescriptor> descriptors = Sets.newHashSet();
|
||||||
@@ -248,12 +249,14 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
context.trace.record(AMBIGUOUS_REFERENCE_TARGET, operationSign, descriptors);
|
context.trace.record(AMBIGUOUS_REFERENCE_TARGET, operationSign, descriptors);
|
||||||
}
|
}
|
||||||
else if (assignmentOperationType != null) {
|
else if (assignmentOperationType != null) {
|
||||||
|
// There's 'plusAssign()', so we do a.plusAssign(b)
|
||||||
assignmentOperationTrace.commit();
|
assignmentOperationTrace.commit();
|
||||||
if (!KotlinBuiltIns.getInstance().isUnit(assignmentOperationType)) {
|
if (!KotlinBuiltIns.getInstance().isUnit(assignmentOperationType)) {
|
||||||
context.trace.report(ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT.on(operationSign, assignmentOperationDescriptors.getResultingDescriptor(), operationSign));
|
context.trace.report(ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT.on(operationSign, assignmentOperationDescriptors.getResultingDescriptor(), operationSign));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// There's only 'plus()', so we try 'a = a + b'
|
||||||
binaryOperationTrace.commit();
|
binaryOperationTrace.commit();
|
||||||
context.trace.record(VARIABLE_REASSIGNMENT, expression);
|
context.trace.record(VARIABLE_REASSIGNMENT, expression);
|
||||||
if (left instanceof JetArrayAccessExpression) {
|
if (left instanceof JetArrayAccessExpression) {
|
||||||
@@ -262,8 +265,8 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
basic.resolveArrayAccessSetMethod((JetArrayAccessExpression) left, right, contextForResolve, context.trace);
|
basic.resolveArrayAccessSetMethod((JetArrayAccessExpression) left, right, contextForResolve, context.trace);
|
||||||
}
|
}
|
||||||
dataFlowInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
|
dataFlowInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
|
||||||
|
basic.checkLValue(context.trace, expression.getLeft());
|
||||||
}
|
}
|
||||||
basic.checkLValue(context.trace, expression.getLeft());
|
|
||||||
temporaryBindingTrace.commit();
|
temporaryBindingTrace.commit();
|
||||||
return JetTypeInfo.create(checkAssignmentType(type, expression, contextWithExpectedType), dataFlowInfo);
|
return JetTypeInfo.create(checkAssignmentType(type, expression, contextWithExpectedType), dataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
class A() {
|
||||||
|
var x = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun A.plusAssign(y: Int) { x += y }
|
||||||
|
fun A.minusAssign(y: Int) { x -= y }
|
||||||
|
fun A.timesAssign(y: Int) { x *= y }
|
||||||
|
fun A.divAssign(y: Int) { x /= y }
|
||||||
|
fun A.modAssign(y: Int) { x %= y }
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val original = A()
|
||||||
|
val a = original
|
||||||
|
|
||||||
|
a += 1
|
||||||
|
if (!(a identityEquals original)) return "Fail 1: $a !== $original"
|
||||||
|
if (a.x != 1) return "Fail 2: ${a.x} != 1"
|
||||||
|
|
||||||
|
a -= 2
|
||||||
|
if (!(a identityEquals original)) return "Fail 3: $a !== $original"
|
||||||
|
if (a.x != -1) return "Fail 4: ${a.x} != -1"
|
||||||
|
|
||||||
|
a *= -10
|
||||||
|
if (!(a identityEquals original)) return "Fail 5: $a !== $original"
|
||||||
|
if (a.x != 10) return "Fail 6: ${a.x} != 10"
|
||||||
|
|
||||||
|
a /= 3
|
||||||
|
if (!(a identityEquals original)) return "Fail 7: $a !== $original"
|
||||||
|
if (a.x != 3) return "Fail 8: ${a.x} != 3"
|
||||||
|
|
||||||
|
a %= 2
|
||||||
|
if (!(a identityEquals original)) return "Fail 9: $a !== $original"
|
||||||
|
if (a.x != 1) return "Fail 10: ${a.x} != 1"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
class A {
|
||||||
|
fun plusAssign(<!UNUSED_PARAMETER!>x<!>: Int) {}
|
||||||
|
fun minusAssign(<!UNUSED_PARAMETER!>x<!>: Int) {}
|
||||||
|
fun timesAssign(<!UNUSED_PARAMETER!>x<!>: Int) {}
|
||||||
|
fun divAssign(<!UNUSED_PARAMETER!>x<!>: Int) {}
|
||||||
|
fun modAssign(<!UNUSED_PARAMETER!>x<!>: Int) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testVal() {
|
||||||
|
val a = A()
|
||||||
|
a += 1
|
||||||
|
a -= 1
|
||||||
|
a *= 1
|
||||||
|
a /= 1
|
||||||
|
a %= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testExpr() {
|
||||||
|
A() += 1
|
||||||
|
A() -= 1
|
||||||
|
A() *= 1
|
||||||
|
A() /= 1
|
||||||
|
A() %= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
fun plus(<!UNUSED_PARAMETER!>x<!>: Int): B = B()
|
||||||
|
fun minus(<!UNUSED_PARAMETER!>x<!>: Int): B = B()
|
||||||
|
fun times(<!UNUSED_PARAMETER!>x<!>: Int): B = B()
|
||||||
|
fun div(<!UNUSED_PARAMETER!>x<!>: Int): B = B()
|
||||||
|
fun mod(<!UNUSED_PARAMETER!>x<!>: Int): B = B()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testWrong() {
|
||||||
|
<!VARIABLE_EXPECTED!>B()<!> += 1
|
||||||
|
<!VARIABLE_EXPECTED!>B()<!> -= 1
|
||||||
|
<!VARIABLE_EXPECTED!>B()<!> *= 1
|
||||||
|
<!VARIABLE_EXPECTED!>B()<!> /= 1
|
||||||
|
<!VARIABLE_EXPECTED!>B()<!> %= 1
|
||||||
|
}
|
||||||
@@ -3076,6 +3076,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
|||||||
doTest("compiler/testData/diagnostics/tests/operatorsOverloading/AssignOperatorAmbiguity.kt");
|
doTest("compiler/testData/diagnostics/tests/operatorsOverloading/AssignOperatorAmbiguity.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AssignmentOperations.kt")
|
||||||
|
public void testAssignmentOperations() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/operatorsOverloading/AssignmentOperations.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("IteratorAmbiguity.kt")
|
@TestMetadata("IteratorAmbiguity.kt")
|
||||||
public void testIteratorAmbiguity() throws Exception {
|
public void testIteratorAmbiguity() throws Exception {
|
||||||
doTest("compiler/testData/diagnostics/tests/operatorsOverloading/IteratorAmbiguity.kt");
|
doTest("compiler/testData/diagnostics/tests/operatorsOverloading/IteratorAmbiguity.kt");
|
||||||
|
|||||||
@@ -2728,6 +2728,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/box/operatorConventions"), Pattern.compile("^(.+)\\.kt$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/box/operatorConventions"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("assignmentOperations.kt")
|
||||||
|
public void testAssignmentOperations() throws Exception {
|
||||||
|
doTest("compiler/testData/codegen/box/operatorConventions/assignmentOperations.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/operatorConventions/compareTo")
|
@TestMetadata("compiler/testData/codegen/box/operatorConventions/compareTo")
|
||||||
public static class CompareTo extends AbstractBlackBoxCodegenTest {
|
public static class CompareTo extends AbstractBlackBoxCodegenTest {
|
||||||
public void testAllFilesPresentInCompareTo() throws Exception {
|
public void testAllFilesPresentInCompareTo() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user