[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,
descriptor: DeclarationDescriptor,
resolvedCall: ResolvedCall<*>?,
origin: IrStatementOrigin?
origin: IrStatementOrigin?,
irType: IrType? = null
): IrExpression =
when (descriptor) {
is FakeCallableDescriptorForObject ->
generateValueReference(startOffset, endOffset, descriptor.getReferencedDescriptor(), resolvedCall, origin)
generateValueReference(startOffset, endOffset, descriptor.getReferencedDescriptor(), resolvedCall, origin, irType)
is TypeAliasDescriptor ->
generateValueReference(startOffset, endOffset, descriptor.classDescriptor!!, null, origin)
generateValueReference(startOffset, endOffset, descriptor.classDescriptor!!, null, origin, irType)
is ClassDescriptor -> {
val classValueType = descriptor.classValueType!!
statementGenerator.generateSingletonReference(descriptor, startOffset, endOffset, classValueType)
@@ -107,7 +108,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
IrGetFieldImpl(startOffset, endOffset, field, fieldType, receiver?.load())
}
is VariableDescriptor ->
generateGetVariable(startOffset, endOffset, descriptor, getTypeArguments(resolvedCall), origin)
generateGetVariable(startOffset, endOffset, descriptor, getTypeArguments(resolvedCall), origin, irType)
else ->
TODO("Unexpected callable descriptor: $descriptor ${descriptor::class.java.simpleName}")
}
@@ -117,7 +118,8 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
endOffset: Int,
descriptor: VariableDescriptor,
typeArguments: Map<TypeParameterDescriptor, KotlinType>?,
origin: IrStatementOrigin? = null
origin: IrStatementOrigin? = null,
irType: IrType? = null
) =
if (descriptor is LocalVariableDescriptor && descriptor.isDelegated) {
val getterDescriptor = descriptor.getter!!
@@ -128,8 +130,15 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
context.callToSubstitutedDescriptorMap[this] = getterDescriptor
putTypeArguments(typeArguments) { it.toIrType() }
}
} else
IrGetValueImpl(startOffset, endOffset, descriptor.type.toIrType(), context.symbolTable.referenceValue(descriptor), origin)
} else {
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 =
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.setExplicitReceiverValue
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContext.SMARTCAST
import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
@@ -327,7 +328,8 @@ class StatementGenerator(
): IrExpression =
CallGenerator(this).generateValueReference(
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 {
@@ -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, С }
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)
enum class MyEnum(val value: String) {
@@ -89,7 +89,7 @@ fun test5(a: Any) {
a as Function1<Int, Unit> /*~> Unit */
{ // BLOCK
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))
}
}
@@ -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
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=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
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
+2 -2
View File
@@ -34,10 +34,10 @@ fun test3(a: Any?, b: Any?): String {
a !is String? -> return ""
}
return { // BLOCK
val tmp0_elvis_lhs: Any? = a
val tmp0_elvis_lhs: String? = a /*as String? */
when {
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=""
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
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.Any? [val]
GET_VAR 'a: kotlin.Any? declared in <root>.test3' type=kotlin.Any? origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.String? [val]
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
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_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
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
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: TYPE_OP type=kotlin.String origin=IMPLICIT_CAST typeOperand=kotlin.String
GET_VAR 'val tmp_2: kotlin.Any? [val] declared in <root>.test3' type=kotlin.Any? origin=null
then: GET_VAR 'val tmp_2: kotlin.String? [val] declared in <root>.test3' type=kotlin.String? origin=null
FUN name:test4 visibility:public modality:FINAL <> (x:kotlin.Any) returnType:kotlin.Any
VALUE_PARAMETER name:x index:0 type:kotlin.Any
BLOCK_BODY
@@ -1,12 +1,6 @@
fun test(x: Any?, y: Double): Boolean {
return when {
x is Int -> less(arg0 = { // BLOCK
val tmp0_safe_receiver: Any? = x
when {
EQEQ(arg0 = tmp0_safe_receiver, arg1 = null) -> null
else -> tmp0_safe_receiver /*as Int */.toDouble()
}
}, arg1 = y)
x is Int -> less(arg0 = x /*as Int */.toDouble(), arg1 = y)
else -> false
}
}
@@ -9,20 +9,9 @@ FILE fqName:<root> fileName:/nullableAnyAsIntToDouble.kt
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
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
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Any? [val]
arg0: 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 '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
BRANCH
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 {
return when {
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 {
return when {
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
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
$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
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]
@@ -56,7 +56,7 @@ FILE fqName:<root> fileName:/implicitCastToNonNull.kt
BRANCH
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
$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
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?]
@@ -1,7 +1,7 @@
fun f(x: Any): String {
when {
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"
}
/*-> @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
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>
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?>?
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?
@@ -4,6 +4,6 @@ fun test1(f: Function1<String, String>): C<@FlexibleNullability String?> {
fun test2(x: Any) {
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
<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?>?
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
@@ -38,6 +38,6 @@ fun testGenericJavaCtor1(f: Function1<String, Int>): G<@FlexibleNullability Stri
fun testGenericJavaCtor2(x: Any) {
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?
<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?>?
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
@@ -26,7 +26,7 @@ fun test4(a: Any) {
fun test5(a: Any) {
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>) {
@@ -35,7 +35,7 @@ fun <T : Any?> test6(a: Function1<T, T>) {
fun <T : Any?> test7(a: Any) {
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?> {
@@ -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
<X>: @[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
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?]
@@ -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
<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?>?
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
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>
@@ -19,9 +19,9 @@ fun test(x: I1) {
x !is I2 -> return Unit
}
// COMPOSITE {
val tmp0_container: I1 = x
val c1: Int = tmp0_container.component1()
val c2: String = tmp0_container /*as I2 */.component2()
val tmp0_container: I2 = x /*as I2 */
val c1: Int = tmp0_container /*as I1 */.component1()
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>'
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
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.I1 [val]
GET_VAR 'x: <root>.I1 declared in <root>.test' type=<root>.I1 origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.I2 [val]
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]
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]
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
GET_VAR 'val tmp_0: <root>.I1 [val] declared in <root>.test' type=<root>.I1 origin=null
$receiver: GET_VAR 'val tmp_0: <root>.I2 [val] declared in <root>.test' type=<root>.I2 origin=null
@@ -78,8 +78,8 @@ class GB<T : Any?, S : Any?> : GA<T> {
fun testGB1(a: Any) {
a as GB<Int, String> /*~> Unit */
a /*as GB<*, *> */.f() /*~> Unit */
a /*as GB<*, *> */.<get-aVal>() /*~> Unit */
a /*as GB<Int, String> */.f() /*~> 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
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
$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
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
$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
FUN FAKE_OVERRIDE name:f visibility:public modality:FINAL <> ($this:<root>.GA<T of <root>.GB>) returnType:kotlin.Int [fake_override]
overridden: