[PSI2IR] Propagate smart cast information for variable loads.

This gives us more precise type information and can enable backend
optimizations. This was motivated by when expressions not compiled
to table switches in the JVM_IR backend.

Fixed KT-36845.
This commit is contained in:
Mads Ager
2020-12-17 12:51:53 +01:00
committed by Dmitry Petrov
parent 98a9e142e8
commit 6fc0de39c2
24 changed files with 59 additions and 69 deletions
@@ -86,13 +86,14 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
endOffset: Int, endOffset: Int,
descriptor: DeclarationDescriptor, descriptor: DeclarationDescriptor,
resolvedCall: ResolvedCall<*>?, resolvedCall: ResolvedCall<*>?,
origin: IrStatementOrigin? origin: IrStatementOrigin?,
irType: IrType? = null
): IrExpression = ): IrExpression =
when (descriptor) { when (descriptor) {
is FakeCallableDescriptorForObject -> is FakeCallableDescriptorForObject ->
generateValueReference(startOffset, endOffset, descriptor.getReferencedDescriptor(), resolvedCall, origin) generateValueReference(startOffset, endOffset, descriptor.getReferencedDescriptor(), resolvedCall, origin, irType)
is TypeAliasDescriptor -> is TypeAliasDescriptor ->
generateValueReference(startOffset, endOffset, descriptor.classDescriptor!!, null, origin) generateValueReference(startOffset, endOffset, descriptor.classDescriptor!!, null, origin, irType)
is ClassDescriptor -> { is ClassDescriptor -> {
val classValueType = descriptor.classValueType!! val classValueType = descriptor.classValueType!!
statementGenerator.generateSingletonReference(descriptor, startOffset, endOffset, classValueType) statementGenerator.generateSingletonReference(descriptor, startOffset, endOffset, classValueType)
@@ -107,7 +108,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
IrGetFieldImpl(startOffset, endOffset, field, fieldType, receiver?.load()) IrGetFieldImpl(startOffset, endOffset, field, fieldType, receiver?.load())
} }
is VariableDescriptor -> is VariableDescriptor ->
generateGetVariable(startOffset, endOffset, descriptor, getTypeArguments(resolvedCall), origin) generateGetVariable(startOffset, endOffset, descriptor, getTypeArguments(resolvedCall), origin, irType)
else -> else ->
TODO("Unexpected callable descriptor: $descriptor ${descriptor::class.java.simpleName}") TODO("Unexpected callable descriptor: $descriptor ${descriptor::class.java.simpleName}")
} }
@@ -117,7 +118,8 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
endOffset: Int, endOffset: Int,
descriptor: VariableDescriptor, descriptor: VariableDescriptor,
typeArguments: Map<TypeParameterDescriptor, KotlinType>?, typeArguments: Map<TypeParameterDescriptor, KotlinType>?,
origin: IrStatementOrigin? = null origin: IrStatementOrigin? = null,
irType: IrType? = null
) = ) =
if (descriptor is LocalVariableDescriptor && descriptor.isDelegated) { if (descriptor is LocalVariableDescriptor && descriptor.isDelegated) {
val getterDescriptor = descriptor.getter!! val getterDescriptor = descriptor.getter!!
@@ -128,8 +130,15 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
context.callToSubstitutedDescriptorMap[this] = getterDescriptor context.callToSubstitutedDescriptorMap[this] = getterDescriptor
putTypeArguments(typeArguments) { it.toIrType() } putTypeArguments(typeArguments) { it.toIrType() }
} }
} else } else {
IrGetValueImpl(startOffset, endOffset, descriptor.type.toIrType(), context.symbolTable.referenceValue(descriptor), origin) val getValue =
IrGetValueImpl(startOffset, endOffset, descriptor.type.toIrType(), context.symbolTable.referenceValue(descriptor), origin)
if (irType != null) {
IrTypeOperatorCallImpl(startOffset, endOffset, irType, IrTypeOperator.IMPLICIT_CAST, irType, getValue)
} else {
getValue
}
}
fun generateDelegatingConstructorCall(startOffset: Int, endOffset: Int, call: CallBuilder): IrExpression = fun generateDelegatingConstructorCall(startOffset: Int, endOffset: Int, call: CallBuilder): IrExpression =
call.callReceiver.call { dispatchReceiver, extensionReceiver -> call.callReceiver.call { dispatchReceiver, extensionReceiver ->
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.psi2ir.intermediate.IntermediateValue
import org.jetbrains.kotlin.psi2ir.intermediate.createTemporaryVariableInBlock import org.jetbrains.kotlin.psi2ir.intermediate.createTemporaryVariableInBlock
import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContext.SMARTCAST
import org.jetbrains.kotlin.resolve.BindingContextUtils import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
@@ -327,7 +328,8 @@ class StatementGenerator(
): IrExpression = ): IrExpression =
CallGenerator(this).generateValueReference( CallGenerator(this).generateValueReference(
expression.startOffsetSkippingComments, expression.endOffset, expression.startOffsetSkippingComments, expression.endOffset,
descriptor, resolvedCall, null descriptor, resolvedCall, null,
context.bindingContext.get(SMARTCAST, expression)?.defaultType?.toIrType()
) )
override fun visitCallExpression(expression: KtCallExpression, data: Nothing?): IrStatement { override fun visitCallExpression(expression: KtCallExpression, data: Nothing?): IrStatement {
@@ -1,6 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// TODO KT-36845 Generate enum-based TABLESWITCH/LOOKUPSWITCH on a value with smart cast to enum in JVM_IR
enum class En { A, B, С } enum class En { A, B, С }
fun box() { fun box() {
@@ -1,6 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// TODO KT-36845 Generate enum-based TABLESWITCH/LOOKUPSWITCH on a value with smart cast to enum in JVM_IR
class EncapsulatedEnum<T : Enum<T>>(val value: T) class EncapsulatedEnum<T : Enum<T>>(val value: T)
enum class MyEnum(val value: String) { enum class MyEnum(val value: String) {
@@ -89,7 +89,7 @@ fun test5(a: Any) {
a as Function1<Int, Unit> /*~> Unit */ a as Function1<Int, Unit> /*~> Unit */
{ // BLOCK { // BLOCK
val tmp0_array: A = A val tmp0_array: A = A
val tmp2_sam: IFoo = a /*as Function1<@ParameterName(name = "i") Int, Unit> */ /*-> IFoo */ val tmp2_sam: IFoo = a /*as Function1<Int, Unit> */ /*-> IFoo */
tmp0_array.set(i = tmp2_sam, newValue = tmp0_array.get(i = tmp2_sam).plus(other = 1)) tmp0_array.set(i = tmp2_sam, newValue = tmp0_array.get(i = tmp2_sam).plus(other = 1))
} }
} }
@@ -199,7 +199,7 @@ FILE fqName:<root> fileName:/caoWithAdaptationForSam.kt
GET_OBJECT 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.A GET_OBJECT 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.A
VAR IR_TEMPORARY_VARIABLE name:tmp_9 type:<root>.IFoo [val] VAR IR_TEMPORARY_VARIABLE name:tmp_9 type:<root>.IFoo [val]
TYPE_OP type=<root>.IFoo origin=SAM_CONVERSION typeOperand=<root>.IFoo TYPE_OP type=<root>.IFoo origin=SAM_CONVERSION typeOperand=<root>.IFoo
TYPE_OP type=kotlin.Function1<@[ParameterName(name = 'i')] kotlin.Int, kotlin.Unit> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<@[ParameterName(name = 'i')] kotlin.Int, kotlin.Unit> TYPE_OP type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<kotlin.Int, kotlin.Unit>
GET_VAR 'a: kotlin.Any declared in <root>.test5' type=kotlin.Any origin=null GET_VAR 'a: kotlin.Any declared in <root>.test5' type=kotlin.Any origin=null
CALL 'public final fun set (i: <root>.IFoo, newValue: kotlin.Int): kotlin.Unit [operator] declared in <root>' type=kotlin.Unit origin=PLUSEQ CALL 'public final fun set (i: <root>.IFoo, newValue: kotlin.Int): kotlin.Unit [operator] declared in <root>' type=kotlin.Unit origin=PLUSEQ
$receiver: GET_VAR 'val tmp_8: <root>.A [val] declared in <root>.test5' type=<root>.A origin=null $receiver: GET_VAR 'val tmp_8: <root>.A [val] declared in <root>.test5' type=<root>.A origin=null
+2 -2
View File
@@ -34,10 +34,10 @@ fun test3(a: Any?, b: Any?): String {
a !is String? -> return "" a !is String? -> return ""
} }
return { // BLOCK return { // BLOCK
val tmp0_elvis_lhs: Any? = a val tmp0_elvis_lhs: String? = a /*as String? */
when { when {
EQEQ(arg0 = tmp0_elvis_lhs, arg1 = null) -> b /*as String */ EQEQ(arg0 = tmp0_elvis_lhs, arg1 = null) -> b /*as String */
else -> tmp0_elvis_lhs /*as String */ else -> tmp0_elvis_lhs
} }
} }
} }
+5 -5
View File
@@ -64,19 +64,19 @@ FILE fqName:<root> fileName:/elvis.kt
CONST String type=kotlin.String value="" CONST String type=kotlin.String value=""
RETURN type=kotlin.Nothing from='public final fun test3 (a: kotlin.Any?, b: kotlin.Any?): kotlin.String declared in <root>' RETURN type=kotlin.Nothing from='public final fun test3 (a: kotlin.Any?, b: kotlin.Any?): kotlin.String declared in <root>'
BLOCK type=kotlin.String origin=ELVIS BLOCK type=kotlin.String origin=ELVIS
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.Any? [val] VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.String? [val]
GET_VAR 'a: kotlin.Any? declared in <root>.test3' type=kotlin.Any? origin=null TYPE_OP type=kotlin.String? origin=IMPLICIT_CAST typeOperand=kotlin.String?
GET_VAR 'a: kotlin.Any? declared in <root>.test3' type=kotlin.Any? origin=null
WHEN type=kotlin.String origin=null WHEN type=kotlin.String origin=null
BRANCH BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp_2: kotlin.Any? [val] declared in <root>.test3' type=kotlin.Any? origin=null arg0: GET_VAR 'val tmp_2: kotlin.String? [val] declared in <root>.test3' type=kotlin.String? origin=null
arg1: CONST Null type=kotlin.Nothing? value=null arg1: CONST Null type=kotlin.Nothing? value=null
then: TYPE_OP type=kotlin.String origin=IMPLICIT_CAST typeOperand=kotlin.String then: TYPE_OP type=kotlin.String origin=IMPLICIT_CAST typeOperand=kotlin.String
GET_VAR 'b: kotlin.Any? declared in <root>.test3' type=kotlin.Any? origin=null GET_VAR 'b: kotlin.Any? declared in <root>.test3' type=kotlin.Any? origin=null
BRANCH BRANCH
if: CONST Boolean type=kotlin.Boolean value=true if: CONST Boolean type=kotlin.Boolean value=true
then: TYPE_OP type=kotlin.String origin=IMPLICIT_CAST typeOperand=kotlin.String then: GET_VAR 'val tmp_2: kotlin.String? [val] declared in <root>.test3' type=kotlin.String? origin=null
GET_VAR 'val tmp_2: kotlin.Any? [val] declared in <root>.test3' type=kotlin.Any? origin=null
FUN name:test4 visibility:public modality:FINAL <> (x:kotlin.Any) returnType:kotlin.Any FUN name:test4 visibility:public modality:FINAL <> (x:kotlin.Any) returnType:kotlin.Any
VALUE_PARAMETER name:x index:0 type:kotlin.Any VALUE_PARAMETER name:x index:0 type:kotlin.Any
BLOCK_BODY BLOCK_BODY
@@ -1,12 +1,6 @@
fun test(x: Any?, y: Double): Boolean { fun test(x: Any?, y: Double): Boolean {
return when { return when {
x is Int -> less(arg0 = { // BLOCK x is Int -> less(arg0 = x /*as Int */.toDouble(), arg1 = y)
val tmp0_safe_receiver: Any? = x
when {
EQEQ(arg0 = tmp0_safe_receiver, arg1 = null) -> null
else -> tmp0_safe_receiver /*as Int */.toDouble()
}
}, arg1 = y)
else -> false else -> false
} }
} }
@@ -9,20 +9,9 @@ FILE fqName:<root> fileName:/nullableAnyAsIntToDouble.kt
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Int if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Int
GET_VAR 'x: kotlin.Any? declared in <root>.test' type=kotlin.Any? origin=null GET_VAR 'x: kotlin.Any? declared in <root>.test' type=kotlin.Any? origin=null
then: CALL 'public final fun less (arg0: kotlin.Double, arg1: kotlin.Double): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT then: CALL 'public final fun less (arg0: kotlin.Double, arg1: kotlin.Double): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: BLOCK type=kotlin.Double? origin=SAFE_CALL arg0: CALL 'public open fun toDouble (): kotlin.Double declared in kotlin.Int' type=kotlin.Double origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Any? [val] $this: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
GET_VAR 'x: kotlin.Any? declared in <root>.test' type=kotlin.Any? origin=null GET_VAR 'x: kotlin.Any? declared in <root>.test' type=kotlin.Any? origin=null
WHEN type=kotlin.Double? origin=null
BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp_0: kotlin.Any? [val] declared in <root>.test' type=kotlin.Any? origin=null
arg1: CONST Null type=kotlin.Nothing? value=null
then: CONST Null type=kotlin.Nothing? value=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CALL 'public open fun toDouble (): kotlin.Double declared in kotlin.Int' type=kotlin.Double origin=null
$this: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
GET_VAR 'val tmp_0: kotlin.Any? [val] declared in <root>.test' type=kotlin.Any? origin=null
arg1: GET_VAR 'y: kotlin.Double declared in <root>.test' type=kotlin.Double origin=null arg1: GET_VAR 'y: kotlin.Double declared in <root>.test' type=kotlin.Double origin=null
BRANCH BRANCH
if: CONST Boolean type=kotlin.Boolean value=true if: CONST Boolean type=kotlin.Boolean value=true
@@ -15,14 +15,14 @@ fun <T : CharSequence?> test2(x: T): Int {
inline fun <reified T : CharSequence?> test3(x: Any): Int { inline fun <reified T : CharSequence?> test3(x: Any): Int {
return when { return when {
x !is T -> 0 x !is T -> 0
else -> x /*as CharSequence */.<get-length>() else -> x /*as T */.<get-length>()
} }
} }
inline fun <reified T : CharSequence> test4(x: Any?): Int { inline fun <reified T : CharSequence> test4(x: Any?): Int {
return when { return when {
x !is T -> 0 x !is T -> 0
else -> x /*as CharSequence */.<get-length>() else -> x /*as T */.<get-length>()
} }
} }
@@ -41,7 +41,7 @@ FILE fqName:<root> fileName:/implicitCastToNonNull.kt
BRANCH BRANCH
if: CONST Boolean type=kotlin.Boolean value=true if: CONST Boolean type=kotlin.Boolean value=true
then: CALL 'public abstract fun <get-length> (): kotlin.Int declared in kotlin.CharSequence' type=kotlin.Int origin=GET_PROPERTY then: CALL 'public abstract fun <get-length> (): kotlin.Int declared in kotlin.CharSequence' type=kotlin.Int origin=GET_PROPERTY
$this: TYPE_OP type=kotlin.CharSequence origin=IMPLICIT_CAST typeOperand=kotlin.CharSequence $this: TYPE_OP type=T of <root>.test3 origin=IMPLICIT_CAST typeOperand=T of <root>.test3
GET_VAR 'x: kotlin.Any declared in <root>.test3' type=kotlin.Any origin=null GET_VAR 'x: kotlin.Any declared in <root>.test3' type=kotlin.Any origin=null
FUN name:test4 visibility:public modality:FINAL <T> (x:kotlin.Any?) returnType:kotlin.Int [inline] FUN name:test4 visibility:public modality:FINAL <T> (x:kotlin.Any?) returnType:kotlin.Int [inline]
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.CharSequence] TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.CharSequence]
@@ -56,7 +56,7 @@ FILE fqName:<root> fileName:/implicitCastToNonNull.kt
BRANCH BRANCH
if: CONST Boolean type=kotlin.Boolean value=true if: CONST Boolean type=kotlin.Boolean value=true
then: CALL 'public abstract fun <get-length> (): kotlin.Int declared in kotlin.CharSequence' type=kotlin.Int origin=GET_PROPERTY then: CALL 'public abstract fun <get-length> (): kotlin.Int declared in kotlin.CharSequence' type=kotlin.Int origin=GET_PROPERTY
$this: TYPE_OP type=kotlin.CharSequence origin=IMPLICIT_CAST typeOperand=kotlin.CharSequence $this: TYPE_OP type=T of <root>.test4 origin=IMPLICIT_CAST typeOperand=T of <root>.test4
GET_VAR 'x: kotlin.Any? declared in <root>.test4' type=kotlin.Any? origin=null GET_VAR 'x: kotlin.Any? declared in <root>.test4' type=kotlin.Any? origin=null
FUN name:test5 visibility:public modality:FINAL <T, S> (x:T of <root>.test5, fn:kotlin.Function1<S of <root>.test5, kotlin.Unit>) returnType:kotlin.Unit FUN name:test5 visibility:public modality:FINAL <T, S> (x:T of <root>.test5, fn:kotlin.Function1<S of <root>.test5, kotlin.Unit>) returnType:kotlin.Unit
TYPE_PARAMETER name:T index:0 variance: superTypes:[S of <root>.test5?] TYPE_PARAMETER name:T index:0 variance: superTypes:[S of <root>.test5?]
@@ -1,7 +1,7 @@
fun f(x: Any): String { fun f(x: Any): String {
when { when {
x is A<*> -> { // BLOCK x is A<*> -> { // BLOCK
return x /*as A<T> */.call(block = local fun <anonymous>(y: Any?): @FlexibleNullability String? { return x /*as A<*> */ /*as A<T> */.call(block = local fun <anonymous>(y: Any?): @FlexibleNullability String? {
return "OK" return "OK"
} }
/*-> @FlexibleNullability I<@FlexibleNullability T?>? */) /*!! String */ /*-> @FlexibleNullability I<@FlexibleNullability T?>? */) /*!! String */
@@ -11,7 +11,8 @@ FILE fqName:<root> fileName:/genericSamSmartcast.kt
TYPE_OP type=kotlin.String origin=IMPLICIT_NOTNULL typeOperand=kotlin.String TYPE_OP type=kotlin.String origin=IMPLICIT_NOTNULL typeOperand=kotlin.String
CALL 'public open fun call (block: @[FlexibleNullability] <root>.A.I<@[FlexibleNullability] T of <root>.A?>?): @[FlexibleNullability] kotlin.String? declared in <root>.A' type=@[FlexibleNullability] kotlin.String? origin=null CALL 'public open fun call (block: @[FlexibleNullability] <root>.A.I<@[FlexibleNullability] T of <root>.A?>?): @[FlexibleNullability] kotlin.String? declared in <root>.A' type=@[FlexibleNullability] kotlin.String? origin=null
$this: TYPE_OP type=<root>.A<T of <root>.A> origin=IMPLICIT_CAST typeOperand=<root>.A<T of <root>.A> $this: TYPE_OP type=<root>.A<T of <root>.A> origin=IMPLICIT_CAST typeOperand=<root>.A<T of <root>.A>
GET_VAR 'x: kotlin.Any declared in <root>.f' type=kotlin.Any origin=null TYPE_OP type=<root>.A<*> origin=IMPLICIT_CAST typeOperand=<root>.A<*>
GET_VAR 'x: kotlin.Any declared in <root>.f' type=kotlin.Any origin=null
block: TYPE_OP type=@[FlexibleNullability] <root>.A.I<@[FlexibleNullability] T of <root>.A?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] <root>.A.I<@[FlexibleNullability] T of <root>.A?>? block: TYPE_OP type=@[FlexibleNullability] <root>.A.I<@[FlexibleNullability] T of <root>.A?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] <root>.A.I<@[FlexibleNullability] T of <root>.A?>?
FUN_EXPR type=kotlin.Function1<kotlin.Any?, @[FlexibleNullability] kotlin.String?> origin=LAMBDA FUN_EXPR type=kotlin.Function1<kotlin.Any?, @[FlexibleNullability] kotlin.String?> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (y:kotlin.Any?) returnType:@[FlexibleNullability] kotlin.String? FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (y:kotlin.Any?) returnType:@[FlexibleNullability] kotlin.String?
@@ -4,6 +4,6 @@ fun test1(f: Function1<String, String>): C<@FlexibleNullability String?> {
fun test2(x: Any) { fun test2(x: Any) {
x as Function1<String, String> /*~> Unit */ x as Function1<String, String> /*~> Unit */
C<@FlexibleNullability String?>(jxx = x /*as Function1<@ParameterName(name = "x") @FlexibleNullability String?, @FlexibleNullability String?> */ /*-> @FlexibleNullability J<@FlexibleNullability String?, @FlexibleNullability String?>? */) /*~> Unit */ C<@FlexibleNullability String?>(jxx = x /*as Function1<String, String> */ /*-> @FlexibleNullability J<@FlexibleNullability String?, @FlexibleNullability String?>? */) /*~> Unit */
} }
@@ -17,5 +17,5 @@ FILE fqName:<root> fileName:/samConversionInGenericConstructorCall.kt
CONSTRUCTOR_CALL 'public constructor <init> (jxx: @[FlexibleNullability] <root>.J<@[FlexibleNullability] X of <root>.C?, @[FlexibleNullability] X of <root>.C?>?) declared in <root>.C' type=<root>.C<@[FlexibleNullability] kotlin.String?> origin=null CONSTRUCTOR_CALL 'public constructor <init> (jxx: @[FlexibleNullability] <root>.J<@[FlexibleNullability] X of <root>.C?, @[FlexibleNullability] X of <root>.C?>?) declared in <root>.C' type=<root>.C<@[FlexibleNullability] kotlin.String?> origin=null
<class: X>: @[FlexibleNullability] kotlin.String? <class: X>: @[FlexibleNullability] kotlin.String?
jxx: TYPE_OP type=@[FlexibleNullability] <root>.J<@[FlexibleNullability] kotlin.String?, @[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] <root>.J<@[FlexibleNullability] kotlin.String?, @[FlexibleNullability] kotlin.String?>? jxx: TYPE_OP type=@[FlexibleNullability] <root>.J<@[FlexibleNullability] kotlin.String?, @[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] <root>.J<@[FlexibleNullability] kotlin.String?, @[FlexibleNullability] kotlin.String?>?
TYPE_OP type=kotlin.Function1<@[ParameterName(name = 'x')] @[FlexibleNullability] kotlin.String?, @[FlexibleNullability] kotlin.String?> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<@[ParameterName(name = 'x')] @[FlexibleNullability] kotlin.String?, @[FlexibleNullability] kotlin.String?> TYPE_OP type=kotlin.Function1<kotlin.String, kotlin.String> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<kotlin.String, kotlin.String>
GET_VAR 'x: kotlin.Any declared in <root>.test2' type=kotlin.Any origin=null GET_VAR 'x: kotlin.Any declared in <root>.test2' type=kotlin.Any origin=null
@@ -38,6 +38,6 @@ fun testGenericJavaCtor1(f: Function1<String, Int>): G<@FlexibleNullability Stri
fun testGenericJavaCtor2(x: Any) { fun testGenericJavaCtor2(x: Any) {
x as Function1<String, Int> /*~> Unit */ x as Function1<String, Int> /*~> Unit */
G<@FlexibleNullability String?, @FlexibleNullability Int?>(x = x /*as Function1<@ParameterName(name = "x") @FlexibleNullability String?, @FlexibleNullability Int?> */ /*-> @FlexibleNullability J<@FlexibleNullability Int?, @FlexibleNullability String?>? */) /*~> Unit */ G<@FlexibleNullability String?, @FlexibleNullability Int?>(x = x /*as Function1<String, Int> */ /*-> @FlexibleNullability J<@FlexibleNullability Int?, @FlexibleNullability String?>? */) /*~> Unit */
} }
@@ -110,5 +110,5 @@ FILE fqName:<root> fileName:/samConversionInGenericConstructorCall_NI.kt
<class: TClass>: @[FlexibleNullability] kotlin.String? <class: TClass>: @[FlexibleNullability] kotlin.String?
<TCtor>: @[FlexibleNullability] kotlin.Int? <TCtor>: @[FlexibleNullability] kotlin.Int?
x: TYPE_OP type=@[FlexibleNullability] <root>.J<@[FlexibleNullability] kotlin.Int?, @[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] <root>.J<@[FlexibleNullability] kotlin.Int?, @[FlexibleNullability] kotlin.String?>? x: TYPE_OP type=@[FlexibleNullability] <root>.J<@[FlexibleNullability] kotlin.Int?, @[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] <root>.J<@[FlexibleNullability] kotlin.Int?, @[FlexibleNullability] kotlin.String?>?
TYPE_OP type=kotlin.Function1<@[ParameterName(name = 'x')] @[FlexibleNullability] kotlin.String?, @[FlexibleNullability] kotlin.Int?> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<@[ParameterName(name = 'x')] @[FlexibleNullability] kotlin.String?, @[FlexibleNullability] kotlin.Int?> TYPE_OP type=kotlin.Function1<kotlin.String, kotlin.Int> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<kotlin.String, kotlin.Int>
GET_VAR 'x: kotlin.Any declared in <root>.testGenericJavaCtor2' type=kotlin.Any origin=null GET_VAR 'x: kotlin.Any declared in <root>.testGenericJavaCtor2' type=kotlin.Any origin=null
@@ -26,7 +26,7 @@ fun test4(a: Any) {
fun test5(a: Any) { fun test5(a: Any) {
a as Function1<String, String> /*~> Unit */ a as Function1<String, String> /*~> Unit */
bar<@FlexibleNullability String?>(j = a /*as Function1<@ParameterName(name = "x") @FlexibleNullability String?, @FlexibleNullability String?> */ /*-> @FlexibleNullability J<@FlexibleNullability String?>? */) bar<@FlexibleNullability String?>(j = a /*as Function1<String, String> */ /*-> @FlexibleNullability J<@FlexibleNullability String?>? */)
} }
fun <T : Any?> test6(a: Function1<T, T>) { fun <T : Any?> test6(a: Function1<T, T>) {
@@ -35,7 +35,7 @@ fun <T : Any?> test6(a: Function1<T, T>) {
fun <T : Any?> test7(a: Any) { fun <T : Any?> test7(a: Any) {
a as Function1<T, T> /*~> Unit */ a as Function1<T, T> /*~> Unit */
bar<@FlexibleNullability T?>(j = a /*as Function1<@ParameterName(name = "x") @FlexibleNullability T?, @FlexibleNullability T?> */ /*-> @FlexibleNullability J<@FlexibleNullability T?>? */) bar<@FlexibleNullability T?>(j = a /*as Function1<T, T> */ /*-> @FlexibleNullability J<@FlexibleNullability T?>? */)
} }
fun test8(efn: @ExtensionFunctionType Function1<String, String>): J<@FlexibleNullability String?> { fun test8(efn: @ExtensionFunctionType Function1<String, String>): J<@FlexibleNullability String?> {
@@ -50,7 +50,7 @@ FILE fqName:<root> fileName:/samConversionToGeneric.kt
CALL 'public open fun bar <X> (j: @[FlexibleNullability] <root>.J<@[FlexibleNullability] X of <root>.H.bar?>?): kotlin.Unit declared in <root>.H' type=kotlin.Unit origin=null CALL 'public open fun bar <X> (j: @[FlexibleNullability] <root>.J<@[FlexibleNullability] X of <root>.H.bar?>?): kotlin.Unit declared in <root>.H' type=kotlin.Unit origin=null
<X>: @[FlexibleNullability] kotlin.String? <X>: @[FlexibleNullability] kotlin.String?
j: TYPE_OP type=@[FlexibleNullability] <root>.J<@[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] <root>.J<@[FlexibleNullability] kotlin.String?>? j: TYPE_OP type=@[FlexibleNullability] <root>.J<@[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] <root>.J<@[FlexibleNullability] kotlin.String?>?
TYPE_OP type=kotlin.Function1<@[ParameterName(name = 'x')] @[FlexibleNullability] kotlin.String?, @[FlexibleNullability] kotlin.String?> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<@[ParameterName(name = 'x')] @[FlexibleNullability] kotlin.String?, @[FlexibleNullability] kotlin.String?> TYPE_OP type=kotlin.Function1<kotlin.String, kotlin.String> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<kotlin.String, kotlin.String>
GET_VAR 'a: kotlin.Any declared in <root>.test5' type=kotlin.Any origin=null GET_VAR 'a: kotlin.Any declared in <root>.test5' type=kotlin.Any origin=null
FUN name:test6 visibility:public modality:FINAL <T> (a:kotlin.Function1<T of <root>.test6, T of <root>.test6>) returnType:kotlin.Unit FUN name:test6 visibility:public modality:FINAL <T> (a:kotlin.Function1<T of <root>.test6, T of <root>.test6>) returnType:kotlin.Unit
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
@@ -70,7 +70,7 @@ FILE fqName:<root> fileName:/samConversionToGeneric.kt
CALL 'public open fun bar <X> (j: @[FlexibleNullability] <root>.J<@[FlexibleNullability] X of <root>.H.bar?>?): kotlin.Unit declared in <root>.H' type=kotlin.Unit origin=null CALL 'public open fun bar <X> (j: @[FlexibleNullability] <root>.J<@[FlexibleNullability] X of <root>.H.bar?>?): kotlin.Unit declared in <root>.H' type=kotlin.Unit origin=null
<X>: @[FlexibleNullability] T of <root>.test7? <X>: @[FlexibleNullability] T of <root>.test7?
j: TYPE_OP type=@[FlexibleNullability] <root>.J<@[FlexibleNullability] T of <root>.test7?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] <root>.J<@[FlexibleNullability] T of <root>.test7?>? j: TYPE_OP type=@[FlexibleNullability] <root>.J<@[FlexibleNullability] T of <root>.test7?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] <root>.J<@[FlexibleNullability] T of <root>.test7?>?
TYPE_OP type=kotlin.Function1<@[ParameterName(name = 'x')] @[FlexibleNullability] T of <root>.test7?, @[FlexibleNullability] T of <root>.test7?> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<@[ParameterName(name = 'x')] @[FlexibleNullability] T of <root>.test7?, @[FlexibleNullability] T of <root>.test7?> TYPE_OP type=kotlin.Function1<T of <root>.test7, T of <root>.test7> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<T of <root>.test7, T of <root>.test7>
GET_VAR 'a: kotlin.Any declared in <root>.test7' type=kotlin.Any origin=null GET_VAR 'a: kotlin.Any declared in <root>.test7' type=kotlin.Any origin=null
FUN name:test8 visibility:public modality:FINAL <> (efn:@[ExtensionFunctionType] kotlin.Function1<kotlin.String, kotlin.String>) returnType:<root>.J<@[FlexibleNullability] kotlin.String?> FUN name:test8 visibility:public modality:FINAL <> (efn:@[ExtensionFunctionType] kotlin.Function1<kotlin.String, kotlin.String>) returnType:<root>.J<@[FlexibleNullability] kotlin.String?>
VALUE_PARAMETER name:efn index:0 type:@[ExtensionFunctionType] kotlin.Function1<kotlin.String, kotlin.String> VALUE_PARAMETER name:efn index:0 type:@[ExtensionFunctionType] kotlin.Function1<kotlin.String, kotlin.String>
@@ -19,9 +19,9 @@ fun test(x: I1) {
x !is I2 -> return Unit x !is I2 -> return Unit
} }
// COMPOSITE { // COMPOSITE {
val tmp0_container: I1 = x val tmp0_container: I2 = x /*as I2 */
val c1: Int = tmp0_container.component1() val c1: Int = tmp0_container /*as I1 */.component1()
val c2: String = tmp0_container /*as I2 */.component2() val c2: String = tmp0_container.component2()
// } // }
} }
@@ -49,12 +49,13 @@ FILE fqName:<root> fileName:/smartCastsWithDestructuring.kt
then: RETURN type=kotlin.Nothing from='public final fun test (x: <root>.I1): kotlin.Unit declared in <root>' then: RETURN type=kotlin.Nothing from='public final fun test (x: <root>.I1): kotlin.Unit declared in <root>'
GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
COMPOSITE type=kotlin.Unit origin=DESTRUCTURING_DECLARATION COMPOSITE type=kotlin.Unit origin=DESTRUCTURING_DECLARATION
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.I1 [val] VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.I2 [val]
GET_VAR 'x: <root>.I1 declared in <root>.test' type=<root>.I1 origin=null TYPE_OP type=<root>.I2 origin=IMPLICIT_CAST typeOperand=<root>.I2
GET_VAR 'x: <root>.I1 declared in <root>.test' type=<root>.I1 origin=null
VAR name:c1 type:kotlin.Int [val] VAR name:c1 type:kotlin.Int [val]
CALL 'public final fun component1 (): kotlin.Int [operator] declared in <root>' type=kotlin.Int origin=COMPONENT_N(index=1) CALL 'public final fun component1 (): kotlin.Int [operator] declared in <root>' type=kotlin.Int origin=COMPONENT_N(index=1)
$receiver: GET_VAR 'val tmp_0: <root>.I1 [val] declared in <root>.test' type=<root>.I1 origin=null $receiver: TYPE_OP type=<root>.I1 origin=IMPLICIT_CAST typeOperand=<root>.I1
GET_VAR 'val tmp_0: <root>.I2 [val] declared in <root>.test' type=<root>.I2 origin=null
VAR name:c2 type:kotlin.String [val] VAR name:c2 type:kotlin.String [val]
CALL 'public final fun component2 (): kotlin.String [operator] declared in <root>' type=kotlin.String origin=COMPONENT_N(index=2) CALL 'public final fun component2 (): kotlin.String [operator] declared in <root>' type=kotlin.String origin=COMPONENT_N(index=2)
$receiver: TYPE_OP type=<root>.I2 origin=IMPLICIT_CAST typeOperand=<root>.I2 $receiver: GET_VAR 'val tmp_0: <root>.I2 [val] declared in <root>.test' type=<root>.I2 origin=null
GET_VAR 'val tmp_0: <root>.I1 [val] declared in <root>.test' type=<root>.I1 origin=null
@@ -78,8 +78,8 @@ class GB<T : Any?, S : Any?> : GA<T> {
fun testGB1(a: Any) { fun testGB1(a: Any) {
a as GB<Int, String> /*~> Unit */ a as GB<Int, String> /*~> Unit */
a /*as GB<*, *> */.f() /*~> Unit */ a /*as GB<Int, String> */.f() /*~> Unit */
a /*as GB<*, *> */.<get-aVal>() /*~> Unit */ a /*as GB<Int, String> */.<get-aVal>() /*~> Unit */
} }
} }
@@ -187,11 +187,11 @@ FILE fqName:<root> fileName:/smartCastOnFakeOverrideReceiver.kt
GET_VAR 'a: kotlin.Any declared in <root>.GB.testGB1' type=kotlin.Any origin=null GET_VAR 'a: kotlin.Any declared in <root>.GB.testGB1' type=kotlin.Any origin=null
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
CALL 'public final fun f (): kotlin.Int [fake_override] declared in <root>.GB' type=kotlin.Int origin=null CALL 'public final fun f (): kotlin.Int [fake_override] declared in <root>.GB' type=kotlin.Int origin=null
$this: TYPE_OP type=<root>.GB<*, *> origin=IMPLICIT_CAST typeOperand=<root>.GB<*, *> $this: TYPE_OP type=<root>.GB<kotlin.Int, kotlin.String> origin=IMPLICIT_CAST typeOperand=<root>.GB<kotlin.Int, kotlin.String>
GET_VAR 'a: kotlin.Any declared in <root>.GB.testGB1' type=kotlin.Any origin=null GET_VAR 'a: kotlin.Any declared in <root>.GB.testGB1' type=kotlin.Any origin=null
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
CALL 'public final fun <get-aVal> (): kotlin.Int [fake_override] declared in <root>.GB' type=kotlin.Int origin=GET_PROPERTY CALL 'public final fun <get-aVal> (): kotlin.Int [fake_override] declared in <root>.GB' type=kotlin.Int origin=GET_PROPERTY
$this: TYPE_OP type=<root>.GB<*, *> origin=IMPLICIT_CAST typeOperand=<root>.GB<*, *> $this: TYPE_OP type=<root>.GB<kotlin.Int, kotlin.String> origin=IMPLICIT_CAST typeOperand=<root>.GB<kotlin.Int, kotlin.String>
GET_VAR 'a: kotlin.Any declared in <root>.GB.testGB1' type=kotlin.Any origin=null GET_VAR 'a: kotlin.Any declared in <root>.GB.testGB1' type=kotlin.Any origin=null
FUN FAKE_OVERRIDE name:f visibility:public modality:FINAL <> ($this:<root>.GA<T of <root>.GB>) returnType:kotlin.Int [fake_override] FUN FAKE_OVERRIDE name:f visibility:public modality:FINAL <> ($this:<root>.GA<T of <root>.GB>) returnType:kotlin.Int [fake_override]
overridden: overridden: