diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt index 525b990afe2..aec93fb7fc1 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt @@ -77,7 +77,8 @@ fun StatementGenerator.generateCallReceiver( ktDefaultElement: KtElement, dispatchReceiver: ReceiverValue?, extensionReceiver: ReceiverValue?, - isSafe: Boolean + isSafe: Boolean, + isAssignmentReceiver: Boolean = false ) : CallReceiver { val dispatchReceiverValue = generateReceiverOrNull(ktDefaultElement, dispatchReceiver) val extensionReceiverValue = generateReceiverOrNull(ktDefaultElement, extensionReceiver) @@ -87,10 +88,10 @@ fun StatementGenerator.generateCallReceiver( SimpleCallReceiver(dispatchReceiverValue, extensionReceiverValue) extensionReceiverValue != null -> SafeCallReceiver(this, ktDefaultElement.startOffset, ktDefaultElement.endOffset, - extensionReceiverValue.load(), dispatchReceiverValue) + extensionReceiverValue.load(), dispatchReceiverValue, isAssignmentReceiver) dispatchReceiverValue != null -> SafeCallReceiver(this, ktDefaultElement.startOffset, ktDefaultElement.endOffset, - dispatchReceiverValue.load(), null) + dispatchReceiverValue.load(), null, isAssignmentReceiver) else -> throw AssertionError("Safe call should have an explicit receiver: ${ktDefaultElement.text}") } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt index 7eaaab6976f..1df54ece6cf 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt @@ -145,7 +145,9 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen } val propertyReceiver = statementGenerator.generateCallReceiver( - ktLeft, resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver, resolvedCall.call.isSafeCall()) + ktLeft, resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver, + isSafe = resolvedCall.call.isSafeCall(), + isAssignmentReceiver = true) val superQualifier = getSuperQualifier(resolvedCall) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt index 947e975ae51..fc93cac07a3 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi2ir.intermediate.* import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument +import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.types.KotlinType import java.util.* @@ -63,7 +64,7 @@ class CallGenerator(statementGenerator: StatementGenerator): StatementGeneratorE val irCall = IrDelegatingConstructorCallImpl(startOffset, endOffset, descriptor, getTypeArguments(call.original)) irCall.dispatchReceiver = dispatchReceiver?.load() irCall.extensionReceiver = extensionReceiver?.load() - addParametersToCall(startOffset, endOffset, call, irCall, descriptor.returnType) + addParametersToCall(startOffset, endOffset, call, irCall, descriptor.builtIns.unitType) } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SafeCallReceiver.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SafeCallReceiver.kt index 8a5e4218be7..3204fd544ba 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SafeCallReceiver.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SafeCallReceiver.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.psi2ir.generators.GeneratorWithScope import org.jetbrains.kotlin.psi2ir.generators.constNull import org.jetbrains.kotlin.psi2ir.generators.equalsNull +import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.makeNullable @@ -31,7 +32,8 @@ class SafeCallReceiver( val startOffset: Int, val endOffset: Int, val explicitReceiver: IrExpression, - val implicitDispatchReceiverValue: IntermediateValue? + val implicitDispatchReceiverValue: IntermediateValue?, + val isAssignmentReceiver: Boolean ) : CallReceiver { override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression { val irTmp = generator.scope.createTemporaryVariable(explicitReceiver, "safe_receiver") @@ -49,7 +51,7 @@ class SafeCallReceiver( } val irResult = withDispatchAndExtensionReceivers(dispatchReceiverValue, extensionReceiverValue) - val resultType = irResult.type.makeNullable() + val resultType = if (isAssignmentReceiver) irResult.type.builtIns.unitType else irResult.type.makeNullable() val irBlock = IrBlockImpl(startOffset, endOffset, resultType, IrStatementOrigin.SAFE_CALL) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt index b52faa246f6..a130a4f1dbc 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt @@ -56,17 +56,35 @@ class InsertImplicitCasts(val builtIns: KotlinBuiltIns): IrElementTransformerVoi return expression } - override fun visitBlock(expression: IrBlock): IrExpression { + override fun visitBlockBody(body: IrBlockBody): IrBody { + body.transformChildrenVoid(this) + + body.statements.forEachIndexed { i, irStatement -> + if (irStatement is IrExpression) { + body.statements[i] = irStatement.coerceToUnit(builtIns.unitType) + } + } + + return body + } + + override fun visitContainerExpression(expression: IrContainerExpression): IrExpression { expression.transformChildrenVoid(this) val type = expression.type - if (expression.statements.isEmpty() || KotlinBuiltIns.isUnit(type) || KotlinBuiltIns.isNothing(type)) { + if (expression.statements.isEmpty()) { return expression } - val lastStatement = expression.statements.last() - if (lastStatement is IrExpression) { - expression.statements[expression.statements.lastIndex] = lastStatement.cast(type) + val lastIndex = expression.statements.lastIndex + expression.statements.forEachIndexed { i, irStatement -> + if (irStatement is IrExpression) { + expression.statements[i] = + if (i == lastIndex) + irStatement.cast(type) + else + irStatement.coerceToUnit(builtIns.unitType) + } } return expression @@ -169,8 +187,10 @@ class InsertImplicitCasts(val builtIns: KotlinBuiltIns): IrElementTransformerVoi private fun IrExpression.cast(expectedType: KotlinType?): IrExpression { if (expectedType == null) return this + if (expectedType.isError) return this - if (KotlinBuiltIns.isUnit(expectedType)) return this // TODO expose coercion to Unit in IR? + + if (KotlinBuiltIns.isUnit(expectedType)) return coerceToUnit(expectedType) val valueType = this.type @@ -189,5 +209,13 @@ class InsertImplicitCasts(val builtIns: KotlinBuiltIns): IrElementTransformerVoi return this } + + private fun IrExpression.coerceToUnit(unitType: KotlinType): IrExpression { + val valueType = this.type + + if (KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, unitType)) return this + + return IrTypeOperatorCallImpl(startOffset, endOffset, unitType, IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, unitType, this) + } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorCall.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorCall.kt index 443149037b2..6787bbd0c8b 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorCall.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorCall.kt @@ -22,6 +22,7 @@ enum class IrTypeOperator { CAST, IMPLICIT_CAST, IMPLICIT_NOTNULL, + IMPLICIT_COERCION_TO_UNIT, SAFE_CAST, INSTANCEOF, NOT_INSTANCEOF; diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrDelegatingConstructorCallImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrDelegatingConstructorCallImpl.kt index f18d20330ce..d8e1d39259d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrDelegatingConstructorCallImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrDelegatingConstructorCallImpl.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.types.KotlinType class IrDelegatingConstructorCallImpl( @@ -27,7 +28,7 @@ class IrDelegatingConstructorCallImpl( endOffset: Int, override val descriptor: ConstructorDescriptor, typeArguments: Map? -) : IrCallWithIndexedArgumentsBase(startOffset, endOffset, descriptor.returnType, descriptor.valueParameters.size, typeArguments), +) : IrCallWithIndexedArgumentsBase(startOffset, endOffset, descriptor.builtIns.unitType, descriptor.valueParameters.size, typeArguments), IrDelegatingConstructorCall { override fun accept(visitor: IrElementVisitor, data: D): R { return visitor.visitDelegatingConstructorCall(this, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrEnumConstructorCallImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrEnumConstructorCallImpl.kt index 157fa325120..282b57bbb7c 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrEnumConstructorCallImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrEnumConstructorCallImpl.kt @@ -20,13 +20,14 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.ir.expressions.IrEnumConstructorCall import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns class IrEnumConstructorCallImpl( startOffset: Int, endOffset: Int, override val descriptor: ConstructorDescriptor, override val enumEntryDescriptor: ClassDescriptor? = null -) : IrCallWithIndexedArgumentsBase(startOffset, endOffset, descriptor.returnType, descriptor.valueParameters.size, null), +) : IrCallWithIndexedArgumentsBase(startOffset, endOffset, descriptor.builtIns.unitType, descriptor.valueParameters.size, null), IrEnumConstructorCall { override fun accept(visitor: IrElementVisitor, data: D): R { return visitor.visitEnumConstructorCall(this, data) diff --git a/compiler/testData/ir/irText/classes/argumentReorderingInDelegatingConstructorCall.txt b/compiler/testData/ir/irText/classes/argumentReorderingInDelegatingConstructorCall.txt index beb7b1ef81e..03754e76ec0 100644 --- a/compiler/testData/ir/irText/classes/argumentReorderingInDelegatingConstructorCall.txt +++ b/compiler/testData/ir/irText/classes/argumentReorderingInDelegatingConstructorCall.txt @@ -25,7 +25,7 @@ FILE /argumentReorderingInDelegatingConstructorCall.kt CLASS CLASS Test1 CONSTRUCTOR public constructor Test1(xx: kotlin.Int, yy: kotlin.Int) BLOCK_BODY - BLOCK type=Base origin=ARGUMENTS_REORDERING_FOR_CALL + BLOCK type=kotlin.Unit origin=ARGUMENTS_REORDERING_FOR_CALL VAR IR_TEMPORARY_VARIABLE val tmp0_y: kotlin.Int GET_VAR 'value-parameter yy: Int' type=kotlin.Int origin=null VAR IR_TEMPORARY_VARIABLE val tmp1_x: kotlin.Int @@ -37,7 +37,7 @@ FILE /argumentReorderingInDelegatingConstructorCall.kt CLASS CLASS Test2 CONSTRUCTOR public constructor Test2(xx: kotlin.Int, yy: kotlin.Int) BLOCK_BODY - BLOCK type=Base origin=ARGUMENTS_REORDERING_FOR_CALL + BLOCK type=kotlin.Unit origin=ARGUMENTS_REORDERING_FOR_CALL VAR IR_TEMPORARY_VARIABLE val tmp0_y: kotlin.Int GET_VAR 'value-parameter yy: Int' type=kotlin.Int origin=null VAR IR_TEMPORARY_VARIABLE val tmp1_x: kotlin.Int @@ -48,7 +48,7 @@ FILE /argumentReorderingInDelegatingConstructorCall.kt INSTANCE_INITIALIZER_CALL classDescriptor='Test2' CONSTRUCTOR public constructor Test2(xxx: kotlin.Int, yyy: kotlin.Int, a: kotlin.Any) BLOCK_BODY - BLOCK type=Test2 origin=ARGUMENTS_REORDERING_FOR_CALL + BLOCK type=kotlin.Unit origin=ARGUMENTS_REORDERING_FOR_CALL VAR IR_TEMPORARY_VARIABLE val tmp0_yy: kotlin.Int GET_VAR 'value-parameter yyy: Int' type=kotlin.Int origin=null VAR IR_TEMPORARY_VARIABLE val tmp1_xx: kotlin.Int diff --git a/compiler/testData/ir/irText/declarations/localDelegatedProperties.txt b/compiler/testData/ir/irText/declarations/localDelegatedProperties.txt index 294c73afd56..4b8225cf2b6 100644 --- a/compiler/testData/ir/irText/declarations/localDelegatedProperties.txt +++ b/compiler/testData/ir/irText/declarations/localDelegatedProperties.txt @@ -46,16 +46,20 @@ FILE /localDelegatedProperties.kt thisRef: CONST Null type=kotlin.Nothing? value='null' property: CALLABLE_REFERENCE 'x: Int' type=kotlin.reflect.KMutableProperty0 origin=PROPERTY_REFERENCE_FOR_DELEGATE value: GET_VAR 'value-parameter value: Int' type=kotlin.Int origin=null - CALL '(Int): Int' type=kotlin.Int origin=EQ - value: CONST Int type=kotlin.Int value='0' - BLOCK type=kotlin.Int origin=POSTFIX_INCR - VAR IR_TEMPORARY_VARIABLE val tmp0: kotlin.Int - CALL '(): Int' type=kotlin.Int origin=POSTFIX_INCR - CALL '(Int): Int' type=kotlin.Int origin=POSTFIX_INCR - value: CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR - $this: GET_VAR 'tmp0: Int' type=kotlin.Int origin=null - GET_VAR 'tmp0: Int' type=kotlin.Int origin=null - CALL '(Int): Int' type=kotlin.Int origin=PLUSEQ - value: CALL 'plus(Int): Int' type=kotlin.Int origin=PLUSEQ - $this: CALL '(): Int' type=kotlin.Int origin=PLUSEQ - other: CONST Int type=kotlin.Int value='1' + TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CALL '(Int): Int' type=kotlin.Int origin=EQ + value: CONST Int type=kotlin.Int value='0' + TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Int origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE val tmp0: kotlin.Int + CALL '(): Int' type=kotlin.Int origin=POSTFIX_INCR + TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CALL '(Int): Int' type=kotlin.Int origin=POSTFIX_INCR + value: CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR + $this: GET_VAR 'tmp0: Int' type=kotlin.Int origin=null + GET_VAR 'tmp0: Int' type=kotlin.Int origin=null + TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CALL '(Int): Int' type=kotlin.Int origin=PLUSEQ + value: CALL 'plus(Int): Int' type=kotlin.Int origin=PLUSEQ + $this: CALL '(): Int' type=kotlin.Int origin=PLUSEQ + other: CONST Int type=kotlin.Int value='1' diff --git a/compiler/testData/ir/irText/expressions/arrayAugmentedAssignment1.txt b/compiler/testData/ir/irText/expressions/arrayAugmentedAssignment1.txt index 85fd2647467..b10ce162f1f 100644 --- a/compiler/testData/ir/irText/expressions/arrayAugmentedAssignment1.txt +++ b/compiler/testData/ir/irText/expressions/arrayAugmentedAssignment1.txt @@ -59,19 +59,20 @@ FILE /arrayAugmentedAssignment1.kt other: CONST Int type=kotlin.Int value='2' FUN public fun testMember(c: C): kotlin.Unit BLOCK_BODY - BLOCK type=kotlin.Int origin=POSTFIX_INCR - VAR IR_TEMPORARY_VARIABLE val tmp0_array: kotlin.IntArray - CALL '(): IntArray' type=kotlin.IntArray origin=GET_PROPERTY - $this: GET_VAR 'value-parameter c: C' type=C origin=null - VAR IR_TEMPORARY_VARIABLE val tmp1_index0: kotlin.Int - CONST Int type=kotlin.Int value='0' - VAR IR_TEMPORARY_VARIABLE val tmp2: kotlin.Int - CALL 'get(Int): Int' type=kotlin.Int origin=POSTFIX_INCR + TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Int origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE val tmp0_array: kotlin.IntArray + CALL '(): IntArray' type=kotlin.IntArray origin=GET_PROPERTY + $this: GET_VAR 'value-parameter c: C' type=C origin=null + VAR IR_TEMPORARY_VARIABLE val tmp1_index0: kotlin.Int + CONST Int type=kotlin.Int value='0' + VAR IR_TEMPORARY_VARIABLE val tmp2: kotlin.Int + CALL 'get(Int): Int' type=kotlin.Int origin=POSTFIX_INCR + $this: GET_VAR 'tmp0_array: IntArray' type=kotlin.IntArray origin=null + index: GET_VAR 'tmp1_index0: Int' type=kotlin.Int origin=null + CALL 'set(Int, Int): Unit' type=kotlin.Unit origin=POSTFIX_INCR $this: GET_VAR 'tmp0_array: IntArray' type=kotlin.IntArray origin=null index: GET_VAR 'tmp1_index0: Int' type=kotlin.Int origin=null - CALL 'set(Int, Int): Unit' type=kotlin.Unit origin=POSTFIX_INCR - $this: GET_VAR 'tmp0_array: IntArray' type=kotlin.IntArray origin=null - index: GET_VAR 'tmp1_index0: Int' type=kotlin.Int 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 + 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 diff --git a/compiler/testData/ir/irText/expressions/coercionToUnit.kt b/compiler/testData/ir/irText/expressions/coercionToUnit.kt new file mode 100644 index 00000000000..6faa687787c --- /dev/null +++ b/compiler/testData/ir/irText/expressions/coercionToUnit.kt @@ -0,0 +1,12 @@ +// +JDK + +val test1: () -> Unit = { 42 } + +fun test2(mc: MutableCollection) { + mc.add("") +} + +fun test3() { + System.out?.println("Hello,") + System.out?.println("world!") +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/coercionToUnit.txt b/compiler/testData/ir/irText/expressions/coercionToUnit.txt new file mode 100644 index 00000000000..49888457a4e --- /dev/null +++ b/compiler/testData/ir/irText/expressions/coercionToUnit.txt @@ -0,0 +1,49 @@ +FILE /coercionToUnit.kt + PROPERTY public val test1: () -> kotlin.Unit + FIELD PROPERTY_BACKING_FIELD public val test1: () -> kotlin.Unit + EXPRESSION_BODY + BLOCK type=() -> kotlin.Unit origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA local final fun (): kotlin.Unit + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Unit' + TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CONST Int type=kotlin.Int value='42' + CALLABLE_REFERENCE '(): Unit' type=() -> kotlin.Unit origin=LAMBDA + FUN DEFAULT_PROPERTY_ACCESSOR public fun (): () -> kotlin.Unit + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): () -> Unit' + GET_FIELD 'test1: () -> Unit' type=() -> kotlin.Unit origin=null + FUN public fun test2(mc: kotlin.collections.MutableCollection): kotlin.Unit + BLOCK_BODY + TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CALL 'add(String): Boolean' type=kotlin.Boolean origin=null + $this: GET_VAR 'value-parameter mc: MutableCollection' type=kotlin.collections.MutableCollection origin=null + element: CONST String type=kotlin.String value='' + FUN public fun test3(): kotlin.Unit + BLOCK_BODY + TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Unit? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE val tmp0_safe_receiver: java.io.PrintStream! + GET_FIELD 'out: PrintStream!' type=java.io.PrintStream! origin=GET_PROPERTY + WHEN type=kotlin.Unit? origin=SAFE_CALL + if: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'tmp0_safe_receiver: PrintStream!' type=java.io.PrintStream! origin=null + arg1: CONST Null type=kotlin.Nothing? value='null' + then: CONST Null type=kotlin.Nothing? value='null' + else: CALL 'println(String!): Unit' type=kotlin.Unit origin=null + $this: TYPE_OP origin=IMPLICIT_NOTNULL typeOperand=java.io.PrintStream + GET_VAR 'tmp0_safe_receiver: PrintStream!' type=java.io.PrintStream! origin=null + p0: CONST String type=kotlin.String value='Hello,' + TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Unit? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE val tmp1_safe_receiver: java.io.PrintStream! + GET_FIELD 'out: PrintStream!' type=java.io.PrintStream! origin=GET_PROPERTY + WHEN type=kotlin.Unit? origin=SAFE_CALL + if: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'tmp1_safe_receiver: PrintStream!' type=java.io.PrintStream! origin=null + arg1: CONST Null type=kotlin.Nothing? value='null' + then: CONST Null type=kotlin.Nothing? value='null' + else: CALL 'println(String!): Unit' type=kotlin.Unit origin=null + $this: TYPE_OP origin=IMPLICIT_NOTNULL typeOperand=java.io.PrintStream + GET_VAR 'tmp1_safe_receiver: PrintStream!' type=java.io.PrintStream! origin=null + p0: CONST String type=kotlin.String value='world!' diff --git a/compiler/testData/ir/irText/expressions/complexAugmentedAssignment.txt b/compiler/testData/ir/irText/expressions/complexAugmentedAssignment.txt index b0e70b06bb8..1e07252104b 100644 --- a/compiler/testData/ir/irText/expressions/complexAugmentedAssignment.txt +++ b/compiler/testData/ir/irText/expressions/complexAugmentedAssignment.txt @@ -60,65 +60,69 @@ FILE /complexAugmentedAssignment.kt BLOCK_BODY VAR var i: kotlin.Int CONST Int type=kotlin.Int value='0' - BLOCK type=kotlin.Int origin=POSTFIX_INCR - VAR IR_TEMPORARY_VARIABLE val tmp1_array: kotlin.IntArray - GET_VAR 'value-parameter a: IntArray' type=kotlin.IntArray origin=null - VAR IR_TEMPORARY_VARIABLE val tmp2_index0: kotlin.Int - BLOCK type=kotlin.Int origin=POSTFIX_INCR - VAR IR_TEMPORARY_VARIABLE val tmp0: kotlin.Int - GET_VAR 'i: Int' type=kotlin.Int origin=POSTFIX_INCR - SET_VAR 'i: Int' type=kotlin.Unit origin=POSTFIX_INCR - CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR - $this: GET_VAR 'tmp0: Int' type=kotlin.Int origin=null - GET_VAR 'tmp0: Int' type=kotlin.Int origin=null - VAR IR_TEMPORARY_VARIABLE val tmp3: kotlin.Int - CALL 'get(Int): Int' type=kotlin.Int origin=POSTFIX_INCR + TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Int origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE val tmp1_array: kotlin.IntArray + GET_VAR 'value-parameter a: IntArray' type=kotlin.IntArray origin=null + VAR IR_TEMPORARY_VARIABLE val tmp2_index0: kotlin.Int + BLOCK type=kotlin.Int origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE val tmp0: kotlin.Int + GET_VAR 'i: Int' type=kotlin.Int origin=POSTFIX_INCR + SET_VAR 'i: Int' type=kotlin.Unit origin=POSTFIX_INCR + CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR + $this: GET_VAR 'tmp0: Int' type=kotlin.Int origin=null + GET_VAR 'tmp0: Int' type=kotlin.Int origin=null + VAR IR_TEMPORARY_VARIABLE val tmp3: kotlin.Int + CALL 'get(Int): Int' type=kotlin.Int origin=POSTFIX_INCR + $this: GET_VAR 'tmp1_array: IntArray' type=kotlin.IntArray origin=null + index: GET_VAR 'tmp2_index0: Int' type=kotlin.Int origin=null + CALL 'set(Int, Int): Unit' type=kotlin.Unit origin=POSTFIX_INCR $this: GET_VAR 'tmp1_array: IntArray' type=kotlin.IntArray origin=null index: GET_VAR 'tmp2_index0: Int' type=kotlin.Int origin=null - CALL 'set(Int, Int): Unit' type=kotlin.Unit origin=POSTFIX_INCR - $this: GET_VAR 'tmp1_array: IntArray' type=kotlin.IntArray origin=null - index: GET_VAR 'tmp2_index0: Int' type=kotlin.Int origin=null - value: CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR - $this: GET_VAR 'tmp3: Int' type=kotlin.Int origin=null - GET_VAR 'tmp3: Int' type=kotlin.Int origin=null - FUN public fun test2(): kotlin.Unit - BLOCK_BODY - BLOCK type=kotlin.Int origin=POSTFIX_INCR - VAR IR_TEMPORARY_VARIABLE val tmp0_this: X1 - GET_OBJECT 'X1' type=X1 - BLOCK type=kotlin.Int origin=POSTFIX_INCR - VAR IR_TEMPORARY_VARIABLE val tmp1: kotlin.Int - CALL '(): Int' type=kotlin.Int origin=POSTFIX_INCR - $this: GET_VAR 'tmp0_this: X1' type=X1 origin=null - CALL '(Int): Unit' type=kotlin.Unit origin=POSTFIX_INCR - $this: GET_VAR 'tmp0_this: X1' type=X1 origin=null - : CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR - $this: GET_VAR 'tmp1: Int' type=kotlin.Int origin=null - GET_VAR 'tmp1: Int' type=kotlin.Int origin=null - BLOCK type=kotlin.Int origin=POSTFIX_INCR - VAR IR_TEMPORARY_VARIABLE val tmp2_this: X1.X2 - GET_OBJECT 'X2' type=X1.X2 - BLOCK type=kotlin.Int origin=POSTFIX_INCR - VAR IR_TEMPORARY_VARIABLE val tmp3: kotlin.Int - CALL '(): Int' type=kotlin.Int origin=POSTFIX_INCR - $this: GET_VAR 'tmp2_this: X1.X2' type=X1.X2 origin=null - CALL '(Int): Unit' type=kotlin.Unit origin=POSTFIX_INCR - $this: GET_VAR 'tmp2_this: X1.X2' type=X1.X2 origin=null - : CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR + value: CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR $this: GET_VAR 'tmp3: Int' type=kotlin.Int origin=null GET_VAR 'tmp3: Int' type=kotlin.Int origin=null - BLOCK type=kotlin.Int origin=POSTFIX_INCR - VAR IR_TEMPORARY_VARIABLE val tmp4_this: X1.X2.X3 - GET_OBJECT 'X3' type=X1.X2.X3 + FUN public fun test2(): kotlin.Unit + BLOCK_BODY + TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit BLOCK type=kotlin.Int origin=POSTFIX_INCR - VAR IR_TEMPORARY_VARIABLE val tmp5: kotlin.Int - CALL '(): Int' type=kotlin.Int origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE val tmp0_this: X1 + GET_OBJECT 'X1' type=X1 + BLOCK type=kotlin.Int origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE val tmp1: kotlin.Int + CALL '(): Int' type=kotlin.Int origin=POSTFIX_INCR + $this: GET_VAR 'tmp0_this: X1' type=X1 origin=null + CALL '(Int): Unit' type=kotlin.Unit origin=POSTFIX_INCR + $this: GET_VAR 'tmp0_this: X1' type=X1 origin=null + : CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR + $this: GET_VAR 'tmp1: Int' type=kotlin.Int origin=null + GET_VAR 'tmp1: Int' type=kotlin.Int origin=null + TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Int origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE val tmp2_this: X1.X2 + GET_OBJECT 'X2' type=X1.X2 + BLOCK type=kotlin.Int origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE val tmp3: kotlin.Int + CALL '(): Int' type=kotlin.Int origin=POSTFIX_INCR + $this: GET_VAR 'tmp2_this: X1.X2' type=X1.X2 origin=null + CALL '(Int): Unit' type=kotlin.Unit origin=POSTFIX_INCR + $this: GET_VAR 'tmp2_this: X1.X2' type=X1.X2 origin=null + : CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR + $this: GET_VAR 'tmp3: Int' type=kotlin.Int origin=null + GET_VAR 'tmp3: Int' type=kotlin.Int origin=null + TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Int origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE val tmp4_this: X1.X2.X3 + GET_OBJECT 'X3' type=X1.X2.X3 + BLOCK type=kotlin.Int origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE val tmp5: kotlin.Int + CALL '(): Int' type=kotlin.Int origin=POSTFIX_INCR + $this: GET_VAR 'tmp4_this: X1.X2.X3' type=X1.X2.X3 origin=null + CALL '(Int): Unit' type=kotlin.Unit origin=POSTFIX_INCR $this: GET_VAR 'tmp4_this: X1.X2.X3' type=X1.X2.X3 origin=null - CALL '(Int): Unit' type=kotlin.Unit origin=POSTFIX_INCR - $this: GET_VAR 'tmp4_this: X1.X2.X3' type=X1.X2.X3 origin=null - : CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR - $this: GET_VAR 'tmp5: Int' type=kotlin.Int origin=null - GET_VAR 'tmp5: Int' type=kotlin.Int origin=null + : CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR + $this: GET_VAR 'tmp5: Int' type=kotlin.Int origin=null + GET_VAR 'tmp5: Int' type=kotlin.Int origin=null CLASS CLASS B CONSTRUCTOR public constructor B(s: kotlin.Int = ...) s: EXPRESSION_BODY diff --git a/compiler/testData/ir/irText/expressions/safeAssignment.kt b/compiler/testData/ir/irText/expressions/safeAssignment.kt new file mode 100644 index 00000000000..57c8bb5bd10 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/safeAssignment.kt @@ -0,0 +1,5 @@ +class C(var x: Int) + +fun test(nc: C?) { + nc?.x = 42 +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/safeAssignment.txt b/compiler/testData/ir/irText/expressions/safeAssignment.txt new file mode 100644 index 00000000000..d9faed3dce4 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/safeAssignment.txt @@ -0,0 +1,34 @@ +FILE /safeAssignment.kt + CLASS CLASS C + CONSTRUCTOR public constructor C(x: kotlin.Int) + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'constructor Any()' + INSTANCE_INITIALIZER_CALL classDescriptor='C' + PROPERTY public final var x: kotlin.Int + FIELD PROPERTY_BACKING_FIELD public final var x: kotlin.Int + EXPRESSION_BODY + GET_VAR 'value-parameter x: Int' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR public final fun (): kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Int' + GET_FIELD 'x: Int' type=kotlin.Int origin=null + receiver: THIS of 'C' type=C + FUN DEFAULT_PROPERTY_ACCESSOR public final fun (: kotlin.Int): kotlin.Unit + BLOCK_BODY + SET_FIELD 'x: Int' type=kotlin.Unit origin=null + receiver: THIS of 'C' type=C + value: GET_VAR 'value-parameter : Int' type=kotlin.Int origin=null + FUN public fun test(nc: C?): kotlin.Unit + BLOCK_BODY + BLOCK type=kotlin.Unit origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE val tmp0_safe_receiver: C? + GET_VAR 'value-parameter nc: C?' type=C? origin=null + WHEN type=kotlin.Unit origin=SAFE_CALL + if: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'tmp0_safe_receiver: C?' type=C? origin=null + arg1: CONST Null type=kotlin.Nothing? value='null' + then: TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CONST Null type=kotlin.Nothing? value='null' + else: CALL '(Int): Unit' type=kotlin.Unit origin=EQ + $this: GET_VAR 'tmp0_safe_receiver: C?' type=C? origin=null + : CONST Int type=kotlin.Int value='42' diff --git a/compiler/testData/ir/irText/expressions/safeCallWithIncrementDecrement.txt b/compiler/testData/ir/irText/expressions/safeCallWithIncrementDecrement.txt index c6d6c5c3d34..affce3b3a6d 100644 --- a/compiler/testData/ir/irText/expressions/safeCallWithIncrementDecrement.txt +++ b/compiler/testData/ir/irText/expressions/safeCallWithIncrementDecrement.txt @@ -32,49 +32,52 @@ FILE /safeCallWithIncrementDecrement.kt BLOCK_BODY FUN public fun testProperty(nc: test.C?): kotlin.Unit BLOCK_BODY - BLOCK type=kotlin.Int? origin=SAFE_CALL + BLOCK type=kotlin.Unit origin=SAFE_CALL VAR IR_TEMPORARY_VARIABLE val tmp0_safe_receiver: test.C? GET_VAR 'value-parameter nc: C?' type=test.C? origin=null - WHEN type=kotlin.Int? origin=SAFE_CALL + WHEN type=kotlin.Unit origin=SAFE_CALL if: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ arg0: GET_VAR 'tmp0_safe_receiver: C?' type=test.C? origin=null arg1: CONST Null type=kotlin.Nothing? value='null' - then: CONST Null type=kotlin.Nothing? value='null' - else: BLOCK type=kotlin.Int origin=POSTFIX_INCR - VAR IR_TEMPORARY_VARIABLE val tmp1_this: test.C? - GET_VAR 'tmp0_safe_receiver: C?' type=test.C? origin=null + then: TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CONST Null type=kotlin.Nothing? value='null' + else: TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit BLOCK type=kotlin.Int origin=POSTFIX_INCR - VAR IR_TEMPORARY_VARIABLE val tmp2: kotlin.Int - CALL '() on C?: Int' type=kotlin.Int origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE val tmp1_this: test.C? + GET_VAR 'tmp0_safe_receiver: C?' type=test.C? origin=null + BLOCK type=kotlin.Int origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE val tmp2: kotlin.Int + CALL '() on C?: Int' type=kotlin.Int origin=POSTFIX_INCR + $this: GET_VAR 'tmp1_this: C?' type=test.C? origin=null + CALL '(Int) on C?: Unit' type=kotlin.Unit origin=POSTFIX_INCR $this: GET_VAR 'tmp1_this: C?' type=test.C? origin=null - CALL '(Int) on C?: Unit' type=kotlin.Unit origin=POSTFIX_INCR - $this: GET_VAR 'tmp1_this: C?' type=test.C? origin=null - value: CALL 'inc() on Int?: Int?' type=kotlin.Int? origin=POSTFIX_INCR - $receiver: GET_VAR 'tmp2: Int' type=kotlin.Int origin=null - GET_VAR 'tmp2: Int' type=kotlin.Int origin=null + value: CALL 'inc() on Int?: Int?' type=kotlin.Int? origin=POSTFIX_INCR + $receiver: GET_VAR 'tmp2: Int' type=kotlin.Int origin=null + GET_VAR 'tmp2: Int' type=kotlin.Int origin=null FUN public fun testArrayAccess(nc: test.C?): kotlin.Unit BLOCK_BODY - BLOCK type=kotlin.Int origin=POSTFIX_INCR - VAR IR_TEMPORARY_VARIABLE val tmp3_array: kotlin.Int? - BLOCK type=kotlin.Int? origin=SAFE_CALL - VAR IR_TEMPORARY_VARIABLE val tmp0_safe_receiver: test.C? - GET_VAR 'value-parameter nc: C?' type=test.C? origin=null - WHEN type=kotlin.Int? origin=SAFE_CALL - if: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'tmp0_safe_receiver: C?' type=test.C? origin=null - arg1: CONST Null type=kotlin.Nothing? value='null' - then: CONST Null type=kotlin.Nothing? value='null' - else: CALL '() on C?: Int' type=kotlin.Int origin=GET_PROPERTY - $this: GET_VAR 'tmp0_safe_receiver: C?' type=test.C? origin=null - VAR IR_TEMPORARY_VARIABLE val tmp4_index0: kotlin.Int - CONST Int type=kotlin.Int value='0' - VAR IR_TEMPORARY_VARIABLE val tmp5: kotlin.Int - CALL 'get(Int) on Int?: Int' type=kotlin.Int origin=POSTFIX_INCR + TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Int origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE val tmp3_array: kotlin.Int? + BLOCK type=kotlin.Int? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE val tmp0_safe_receiver: test.C? + GET_VAR 'value-parameter nc: C?' type=test.C? origin=null + WHEN type=kotlin.Int? origin=SAFE_CALL + if: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'tmp0_safe_receiver: C?' type=test.C? origin=null + arg1: CONST Null type=kotlin.Nothing? value='null' + then: CONST Null type=kotlin.Nothing? value='null' + else: CALL '() on C?: Int' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'tmp0_safe_receiver: C?' type=test.C? origin=null + VAR IR_TEMPORARY_VARIABLE val tmp4_index0: kotlin.Int + CONST Int type=kotlin.Int value='0' + VAR IR_TEMPORARY_VARIABLE val tmp5: kotlin.Int + CALL 'get(Int) on Int?: Int' type=kotlin.Int origin=POSTFIX_INCR + $receiver: GET_VAR 'tmp3_array: Int?' type=kotlin.Int? origin=null + index: GET_VAR 'tmp4_index0: Int' type=kotlin.Int origin=null + CALL 'set(Int, Int) on Int?: Unit' type=kotlin.Unit origin=POSTFIX_INCR $receiver: GET_VAR 'tmp3_array: Int?' type=kotlin.Int? origin=null index: GET_VAR 'tmp4_index0: Int' type=kotlin.Int origin=null - CALL 'set(Int, Int) on Int?: Unit' type=kotlin.Unit origin=POSTFIX_INCR - $receiver: GET_VAR 'tmp3_array: Int?' type=kotlin.Int? origin=null - index: GET_VAR 'tmp4_index0: Int' type=kotlin.Int origin=null - value: CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR - $this: GET_VAR 'tmp5: Int' type=kotlin.Int origin=null - GET_VAR 'tmp5: Int' type=kotlin.Int origin=null + value: CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR + $this: GET_VAR 'tmp5: Int' type=kotlin.Int origin=null + GET_VAR 'tmp5: Int' type=kotlin.Int origin=null diff --git a/compiler/testData/ir/irText/expressions/safeCalls.txt b/compiler/testData/ir/irText/expressions/safeCalls.txt index 5519520ed3b..2b3f0a76cdd 100644 --- a/compiler/testData/ir/irText/expressions/safeCalls.txt +++ b/compiler/testData/ir/irText/expressions/safeCalls.txt @@ -66,14 +66,15 @@ FILE /safeCalls.kt other: GET_VAR 'value-parameter y: Any?' type=kotlin.Any? origin=null FUN public fun test4(x: Ref?): kotlin.Unit BLOCK_BODY - BLOCK type=kotlin.Unit? origin=SAFE_CALL + BLOCK type=kotlin.Unit origin=SAFE_CALL VAR IR_TEMPORARY_VARIABLE val tmp0_safe_receiver: Ref? GET_VAR 'value-parameter x: Ref?' type=Ref? origin=null - WHEN type=kotlin.Unit? origin=SAFE_CALL + WHEN type=kotlin.Unit origin=SAFE_CALL if: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQ arg0: GET_VAR 'tmp0_safe_receiver: Ref?' type=Ref? origin=null arg1: CONST Null type=kotlin.Nothing? value='null' - then: CONST Null type=kotlin.Nothing? value='null' + then: TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CONST Null type=kotlin.Nothing? value='null' else: CALL '(Int): Unit' type=kotlin.Unit origin=EQ $this: GET_VAR 'tmp0_safe_receiver: Ref?' type=Ref? origin=null : CONST Int type=kotlin.Int value='0' diff --git a/compiler/testData/ir/irText/expressions/whileDoWhile.txt b/compiler/testData/ir/irText/expressions/whileDoWhile.txt index aa9b6500c20..4c6539fc336 100644 --- a/compiler/testData/ir/irText/expressions/whileDoWhile.txt +++ b/compiler/testData/ir/irText/expressions/whileDoWhile.txt @@ -52,13 +52,14 @@ FILE /whileDoWhile.kt other: CONST Int type=kotlin.Int value='15' DO_WHILE label=null origin=DO_WHILE_LOOP body: BLOCK type=kotlin.Unit origin=null - BLOCK type=kotlin.Int origin=POSTFIX_INCR - VAR IR_TEMPORARY_VARIABLE val tmp3: kotlin.Int - GET_VAR 'x: Int' type=kotlin.Int origin=POSTFIX_INCR - SET_VAR 'x: Int' type=kotlin.Unit origin=POSTFIX_INCR - CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR - $this: GET_VAR 'tmp3: Int' type=kotlin.Int origin=null - GET_VAR 'tmp3: Int' type=kotlin.Int origin=null + TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Int origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE val tmp3: kotlin.Int + GET_VAR 'x: Int' type=kotlin.Int origin=POSTFIX_INCR + SET_VAR 'x: Int' type=kotlin.Unit origin=POSTFIX_INCR + CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR + $this: GET_VAR 'tmp3: Int' type=kotlin.Int origin=null + GET_VAR 'tmp3: Int' type=kotlin.Int origin=null condition: CALL 'LT0(Int): Boolean' type=kotlin.Boolean origin=LT arg0: CALL 'compareTo(Int): Int' type=kotlin.Int origin=LT $this: GET_VAR 'x: Int' type=kotlin.Int origin=null diff --git a/compiler/testData/ir/irText/lambdas/localFunction.txt b/compiler/testData/ir/irText/lambdas/localFunction.txt index bf7e961f64b..d00a95bd0ef 100644 --- a/compiler/testData/ir/irText/lambdas/localFunction.txt +++ b/compiler/testData/ir/irText/lambdas/localFunction.txt @@ -5,11 +5,12 @@ FILE /localFunction.kt CONST Int type=kotlin.Int value='0' FUN local final fun local(): kotlin.Unit BLOCK_BODY - BLOCK type=kotlin.Int origin=POSTFIX_INCR - VAR IR_TEMPORARY_VARIABLE val tmp0: kotlin.Int - GET_VAR 'x: Int' type=kotlin.Int origin=POSTFIX_INCR - SET_VAR 'x: Int' type=kotlin.Unit origin=POSTFIX_INCR - CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR - $this: GET_VAR 'tmp0: Int' type=kotlin.Int origin=null - GET_VAR 'tmp0: Int' type=kotlin.Int origin=null + TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Int origin=POSTFIX_INCR + VAR IR_TEMPORARY_VARIABLE val tmp0: kotlin.Int + GET_VAR 'x: Int' type=kotlin.Int origin=POSTFIX_INCR + SET_VAR 'x: Int' type=kotlin.Unit origin=POSTFIX_INCR + CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR + $this: GET_VAR 'tmp0: Int' type=kotlin.Int origin=null + GET_VAR 'tmp0: Int' type=kotlin.Int origin=null CALL 'local(): Unit' type=kotlin.Unit origin=null diff --git a/compiler/testData/ir/irText/lambdas/multipleImplicitReceivers.txt b/compiler/testData/ir/irText/lambdas/multipleImplicitReceivers.txt index dcbd8414185..1c8459b5e0c 100644 --- a/compiler/testData/ir/irText/lambdas/multipleImplicitReceivers.txt +++ b/compiler/testData/ir/irText/lambdas/multipleImplicitReceivers.txt @@ -22,35 +22,36 @@ FILE /multipleImplicitReceivers.kt CONST Int type=kotlin.Int value='42' FUN public fun test(fooImpl: IFoo, invokeImpl: IInvoke): kotlin.Unit BLOCK_BODY - CALL 'with(A, A.() -> Int): Int' type=kotlin.Int origin=null - : A - : Int - receiver: GET_OBJECT 'A' type=A - block: BLOCK type=A.() -> kotlin.Int origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA local final fun A.(): kotlin.Int - BLOCK_BODY - RETURN type=kotlin.Nothing from='() on A: Int' - CALL 'with(IFoo, IFoo.() -> Int): Int' type=kotlin.Int origin=null - : IFoo - : Int - receiver: GET_VAR 'value-parameter fooImpl: IFoo' type=IFoo origin=null - block: BLOCK type=IFoo.() -> kotlin.Int origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA local final fun IFoo.(): kotlin.Int - BLOCK_BODY - RETURN type=kotlin.Nothing from='() on IFoo: Int' - CALL 'with(IInvoke, IInvoke.() -> Int): Int' type=kotlin.Int origin=null - : IInvoke - : Int - receiver: GET_VAR 'value-parameter invokeImpl: IInvoke' type=IInvoke origin=null - block: BLOCK type=IInvoke.() -> kotlin.Int origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA local final fun IInvoke.(): kotlin.Int - BLOCK_BODY - RETURN type=kotlin.Nothing from='() on IInvoke: Int' - CALL 'invoke() on B: Int' type=kotlin.Int origin=INVOKE - $this: $RECEIVER of '() on IInvoke: Int' type=IInvoke - $receiver: CALL '() on A: B' type=B origin=GET_PROPERTY - $this: $RECEIVER of '() on IFoo: Int' type=IFoo - $receiver: $RECEIVER of '() on A: Int' type=A - CALLABLE_REFERENCE '() on IInvoke: Int' type=IInvoke.() -> kotlin.Int origin=LAMBDA - CALLABLE_REFERENCE '() on IFoo: Int' type=IFoo.() -> kotlin.Int origin=LAMBDA - CALLABLE_REFERENCE '() on A: Int' type=A.() -> kotlin.Int origin=LAMBDA + TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CALL 'with(A, A.() -> Int): Int' type=kotlin.Int origin=null + : A + : Int + receiver: GET_OBJECT 'A' type=A + block: BLOCK type=A.() -> kotlin.Int origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA local final fun A.(): kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='() on A: Int' + CALL 'with(IFoo, IFoo.() -> Int): Int' type=kotlin.Int origin=null + : IFoo + : Int + receiver: GET_VAR 'value-parameter fooImpl: IFoo' type=IFoo origin=null + block: BLOCK type=IFoo.() -> kotlin.Int origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA local final fun IFoo.(): kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='() on IFoo: Int' + CALL 'with(IInvoke, IInvoke.() -> Int): Int' type=kotlin.Int origin=null + : IInvoke + : Int + receiver: GET_VAR 'value-parameter invokeImpl: IInvoke' type=IInvoke origin=null + block: BLOCK type=IInvoke.() -> kotlin.Int origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA local final fun IInvoke.(): kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='() on IInvoke: Int' + CALL 'invoke() on B: Int' type=kotlin.Int origin=INVOKE + $this: $RECEIVER of '() on IInvoke: Int' type=IInvoke + $receiver: CALL '() on A: B' type=B origin=GET_PROPERTY + $this: $RECEIVER of '() on IFoo: Int' type=IFoo + $receiver: $RECEIVER of '() on A: Int' type=A + CALLABLE_REFERENCE '() on IInvoke: Int' type=IInvoke.() -> kotlin.Int origin=LAMBDA + CALLABLE_REFERENCE '() on IFoo: Int' type=IFoo.() -> kotlin.Int origin=LAMBDA + CALLABLE_REFERENCE '() on A: Int' type=A.() -> kotlin.Int origin=LAMBDA diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index 7ccab573575..15f35169576 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -382,6 +382,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { doTest(fileName); } + @TestMetadata("coercionToUnit.kt") + public void testCoercionToUnit() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/coercionToUnit.kt"); + doTest(fileName); + } + @TestMetadata("complexAugmentedAssignment.kt") public void testComplexAugmentedAssignment() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/complexAugmentedAssignment.kt"); @@ -514,6 +520,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { doTest(fileName); } + @TestMetadata("safeAssignment.kt") + public void testSafeAssignment() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/safeAssignment.kt"); + doTest(fileName); + } + @TestMetadata("safeCallWithIncrementDecrement.kt") public void testSafeCallWithIncrementDecrement() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/safeCallWithIncrementDecrement.kt");