Postpone call arguments generation in compound assignment expressions
Otherwise RHS is generated twice, causing ISE in symbol binding
This commit is contained in:
+2
-2
@@ -232,7 +232,7 @@ fun StatementGenerator.pregenerateCall(resolvedCall: ResolvedCall<*>): CallBuild
|
|||||||
return pregenerateExtensionInvokeCall(resolvedCall)
|
return pregenerateExtensionInvokeCall(resolvedCall)
|
||||||
}
|
}
|
||||||
|
|
||||||
val call = pregenerateCallWithReceivers(resolvedCall)
|
val call = pregenerateCallReceivers(resolvedCall)
|
||||||
pregenerateValueArguments(call, resolvedCall)
|
pregenerateValueArguments(call, resolvedCall)
|
||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
@@ -310,7 +310,7 @@ private fun StatementGenerator.pregenerateValueArguments(call: CallBuilder, reso
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun StatementGenerator.pregenerateCallWithReceivers(resolvedCall: ResolvedCall<*>): CallBuilder {
|
fun StatementGenerator.pregenerateCallReceivers(resolvedCall: ResolvedCall<*>): CallBuilder {
|
||||||
val call = CallBuilder(resolvedCall, unwrapCallableDescriptor(resolvedCall.resultingDescriptor))
|
val call = CallBuilder(resolvedCall, unwrapCallableDescriptor(resolvedCall.resultingDescriptor))
|
||||||
|
|
||||||
call.callReceiver = generateCallReceiver(resolvedCall.call.callElement,
|
call.callReceiver = generateCallReceiver(resolvedCall.call.callElement,
|
||||||
|
|||||||
+3
-3
@@ -50,7 +50,7 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
|
|||||||
val irAssignmentReceiver = generateAssignmentReceiver(ktLeft, origin)
|
val irAssignmentReceiver = generateAssignmentReceiver(ktLeft, origin)
|
||||||
|
|
||||||
return irAssignmentReceiver.assign { irLValue ->
|
return irAssignmentReceiver.assign { irLValue ->
|
||||||
val opCall = statementGenerator.pregenerateCall(opResolvedCall)
|
val opCall = statementGenerator.pregenerateCallReceivers(opResolvedCall)
|
||||||
opCall.setExplicitReceiverValue(irLValue)
|
opCall.setExplicitReceiverValue(irLValue)
|
||||||
opCall.irValueArgumentsByIndex[0] = statementGenerator.generateExpression(ktRight)
|
opCall.irValueArgumentsByIndex[0] = statementGenerator.generateExpression(ktRight)
|
||||||
val irOpCall = CallGenerator(statementGenerator).generateCall(expression, opCall, origin)
|
val irOpCall = CallGenerator(statementGenerator).generateCall(expression, opCall, origin)
|
||||||
@@ -239,10 +239,10 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
|
|||||||
val irIndexExpressions = ktLeft.indexExpressions.map { statementGenerator.generateExpression(it) }
|
val irIndexExpressions = ktLeft.indexExpressions.map { statementGenerator.generateExpression(it) }
|
||||||
|
|
||||||
val indexedGetResolvedCall = get(BindingContext.INDEXED_LVALUE_GET, ktLeft)
|
val indexedGetResolvedCall = get(BindingContext.INDEXED_LVALUE_GET, ktLeft)
|
||||||
val indexedGetCall = indexedGetResolvedCall?.let { statementGenerator.pregenerateCallWithReceivers(it) }
|
val indexedGetCall = indexedGetResolvedCall?.let { statementGenerator.pregenerateCallReceivers(it) }
|
||||||
|
|
||||||
val indexedSetResolvedCall = get(BindingContext.INDEXED_LVALUE_SET, ktLeft)
|
val indexedSetResolvedCall = get(BindingContext.INDEXED_LVALUE_SET, ktLeft)
|
||||||
val indexedSetCall = indexedSetResolvedCall?.let { statementGenerator.pregenerateCallWithReceivers(it) }
|
val indexedSetCall = indexedSetResolvedCall?.let { statementGenerator.pregenerateCallReceivers(it) }
|
||||||
|
|
||||||
return ArrayAccessAssignmentReceiver(irArray, irIndexExpressions, indexedGetCall, indexedSetCall,
|
return ArrayAccessAssignmentReceiver(irArray, irIndexExpressions, indexedGetCall, indexedSetCall,
|
||||||
CallGenerator(statementGenerator),
|
CallGenerator(statementGenerator),
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
operator fun Any.plusAssign(lambda: () -> Unit) {}
|
||||||
|
|
||||||
|
operator fun Any.get(index: () -> Unit): Int = 42
|
||||||
|
operator fun Any.set(index: () -> Unit, value: Int) {}
|
||||||
|
|
||||||
|
fun test1(a: Any) {
|
||||||
|
a += { }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test2(a: Any) {
|
||||||
|
a[{}] += 42
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test3(a: Any) {
|
||||||
|
a[{}]++
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
FILE /lambdaInCAO.kt
|
||||||
|
FUN public operator fun kotlin.Any.plusAssign(lambda: () -> kotlin.Unit): kotlin.Unit
|
||||||
|
$receiver: VALUE_PARAMETER this@plusAssign: Any
|
||||||
|
VALUE_PARAMETER value-parameter lambda: () -> kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
FUN public operator fun kotlin.Any.get(index: () -> kotlin.Unit): kotlin.Int
|
||||||
|
$receiver: VALUE_PARAMETER this@get: Any
|
||||||
|
VALUE_PARAMETER value-parameter index: () -> kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='get(() -> Unit) on Any: Int'
|
||||||
|
CONST Int type=kotlin.Int value='42'
|
||||||
|
FUN public operator fun kotlin.Any.set(index: () -> kotlin.Unit, value: kotlin.Int): kotlin.Unit
|
||||||
|
$receiver: VALUE_PARAMETER this@set: Any
|
||||||
|
VALUE_PARAMETER value-parameter index: () -> kotlin.Unit
|
||||||
|
VALUE_PARAMETER value-parameter value: kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
FUN public fun test1(a: kotlin.Any): kotlin.Unit
|
||||||
|
VALUE_PARAMETER value-parameter a: kotlin.Any
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'plusAssign(() -> Unit) on Any: Unit' type=kotlin.Unit origin=PLUSEQ
|
||||||
|
$receiver: GET_VAR 'value-parameter a: Any' type=kotlin.Any origin=PLUSEQ
|
||||||
|
lambda: BLOCK type=() -> kotlin.Unit origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA local final fun <anonymous>(): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='<anonymous>(): Unit'
|
||||||
|
GET_OBJECT 'Unit' type=kotlin.Unit
|
||||||
|
FUNCTION_REFERENCE '<anonymous>(): Unit' type=() -> kotlin.Unit origin=LAMBDA
|
||||||
|
FUN public fun test2(a: kotlin.Any): kotlin.Unit
|
||||||
|
VALUE_PARAMETER value-parameter a: kotlin.Any
|
||||||
|
BLOCK_BODY
|
||||||
|
BLOCK type=kotlin.Unit origin=PLUSEQ
|
||||||
|
VAR IR_TEMPORARY_VARIABLE val tmp0_array: kotlin.Any
|
||||||
|
GET_VAR 'value-parameter a: Any' type=kotlin.Any origin=null
|
||||||
|
VAR IR_TEMPORARY_VARIABLE val tmp1_index0: () -> kotlin.Unit
|
||||||
|
BLOCK type=() -> kotlin.Unit origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA local final fun <anonymous>(): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='<anonymous>(): Unit'
|
||||||
|
GET_OBJECT 'Unit' type=kotlin.Unit
|
||||||
|
FUNCTION_REFERENCE '<anonymous>(): Unit' type=() -> kotlin.Unit origin=LAMBDA
|
||||||
|
CALL 'set(() -> Unit, Int) on Any: Unit' type=kotlin.Unit origin=PLUSEQ
|
||||||
|
$receiver: GET_VAR 'tmp0_array: Any' type=kotlin.Any origin=null
|
||||||
|
index: GET_VAR 'tmp1_index0: () -> Unit' type=() -> kotlin.Unit origin=null
|
||||||
|
value: CALL 'plus(Int): Int' type=kotlin.Int origin=PLUSEQ
|
||||||
|
$this: CALL 'get(() -> Unit) on Any: Int' type=kotlin.Int origin=PLUSEQ
|
||||||
|
$receiver: GET_VAR 'tmp0_array: Any' type=kotlin.Any origin=null
|
||||||
|
index: GET_VAR 'tmp1_index0: () -> Unit' type=() -> kotlin.Unit origin=null
|
||||||
|
other: CONST Int type=kotlin.Int value='42'
|
||||||
|
FUN public fun test3(a: kotlin.Any): kotlin.Unit
|
||||||
|
VALUE_PARAMETER value-parameter a: kotlin.Any
|
||||||
|
BLOCK_BODY
|
||||||
|
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
|
||||||
|
BLOCK type=kotlin.Int origin=POSTFIX_INCR
|
||||||
|
VAR IR_TEMPORARY_VARIABLE val tmp0_array: kotlin.Any
|
||||||
|
GET_VAR 'value-parameter a: Any' type=kotlin.Any origin=null
|
||||||
|
VAR IR_TEMPORARY_VARIABLE val tmp1_index0: () -> kotlin.Unit
|
||||||
|
BLOCK type=() -> kotlin.Unit origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA local final fun <anonymous>(): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='<anonymous>(): Unit'
|
||||||
|
GET_OBJECT 'Unit' type=kotlin.Unit
|
||||||
|
FUNCTION_REFERENCE '<anonymous>(): Unit' type=() -> kotlin.Unit origin=LAMBDA
|
||||||
|
VAR IR_TEMPORARY_VARIABLE val tmp2: kotlin.Int
|
||||||
|
CALL 'get(() -> Unit) on Any: Int' type=kotlin.Int origin=POSTFIX_INCR
|
||||||
|
$receiver: GET_VAR 'tmp0_array: Any' type=kotlin.Any origin=null
|
||||||
|
index: GET_VAR 'tmp1_index0: () -> Unit' type=() -> kotlin.Unit origin=null
|
||||||
|
CALL 'set(() -> Unit, Int) on Any: Unit' type=kotlin.Unit origin=POSTFIX_INCR
|
||||||
|
$receiver: GET_VAR 'tmp0_array: Any' type=kotlin.Any origin=null
|
||||||
|
index: GET_VAR 'tmp1_index0: () -> Unit' type=() -> kotlin.Unit origin=null
|
||||||
|
value: CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR
|
||||||
|
$this: GET_VAR 'tmp2: Int' type=kotlin.Int origin=null
|
||||||
|
GET_VAR 'tmp2: Int' type=kotlin.Int origin=null
|
||||||
@@ -737,6 +737,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("lambdaInCAO.kt")
|
||||||
|
public void testLambdaInCAO() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/lambdaInCAO.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("literals.kt")
|
@TestMetadata("literals.kt")
|
||||||
public void testLiterals() throws Exception {
|
public void testLiterals() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/literals.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/literals.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user