[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:
@@ -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 ->
|
||||
|
||||
+3
-1
@@ -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) {
|
||||
|
||||
+1
-1
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
+1
-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
@@ -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
@@ -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
|
||||
|
||||
Vendored
+1
-7
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+2
-13
@@ -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?
|
||||
|
||||
+1
-1
@@ -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 */
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
Vendored
+1
-1
@@ -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 */
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user