diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt index 8f43983c2be..eafe4644470 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.fir.backend.generators -import org.jetbrains.kotlin.builtins.functions.FunctionClassKind import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.backend.* @@ -14,19 +13,12 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.render -import org.jetbrains.kotlin.fir.resolve.createFunctionalType -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider -import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType -import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType -import org.jetbrains.kotlin.fir.resolve.providers.getClassDeclaredCallableSymbols -import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl +import org.jetbrains.kotlin.fir.resolve.inference.* import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.coneType -import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor @@ -44,7 +36,6 @@ import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.ir.types.typeOrNull import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.utils.SmartList @@ -129,14 +120,8 @@ internal class AdapterGenerator( return hasSpreadCase } - internal fun ConeKotlinType.kFunctionTypeToFunctionType(): IrSimpleType { - val kind = - if (isSuspendFunctionType(session)) FunctionClassKind.SuspendFunction - else FunctionClassKind.Function - val functionalTypeId = ClassId(kind.packageFqName, kind.numberedClassName(typeArguments.size - 1)) - val coneType = ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(functionalTypeId), typeArguments, isNullable = false) - return coneType.toIrType() as IrSimpleType - } + internal fun ConeKotlinType.kFunctionTypeToFunctionType(): IrSimpleType = + kFunctionTypeToFunctionType(session).toIrType() as IrSimpleType internal fun generateAdaptedCallableReference( callableReferenceAccess: FirCallableReferenceAccess, @@ -407,7 +392,7 @@ internal class AdapterGenerator( * * At the use site, instead of the argument, we can put the suspend lambda as an adapter. * - * Instead of functions, a class with an overridden invoke can be used too: + * Instead of functions, a subtype of functional type can be used too: * class Foo { * override fun invoke() = ... * } @@ -421,13 +406,16 @@ internal class AdapterGenerator( if (this is IrBlock && origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE) { return this } - if (parameter?.returnTypeRef?.coneType?.isSuspendFunctionType(session) != true) { + val expectedType = parameter?.returnTypeRef?.coneType ?: return this + // Expect the expected type to be a suspend functional type, and the argument type is not a suspend functional type. + if (!expectedType.isSuspendFunctionType(session) || argument.typeRef.coneType.isSuspendFunctionType(session)) { return this } + val expectedFunctionalType = expectedType.suspendFunctionTypeToFunctionType(session) - val suspendConvertedType = parameter.returnTypeRef.toIrType() as IrSimpleType + val invokeSymbol = findInvokeSymbol(expectedFunctionalType, argument) ?: return this + val suspendConvertedType = expectedType.toIrType() as IrSimpleType val returnType = suspendConvertedType.arguments.last().typeOrNull!! - val invokeSymbol = findInvokeSymbol(suspendConvertedType, argument) ?: return this return argument.convertWithOffsets { startOffset, endOffset -> val irAdapterFunction = createAdapterFunctionForArgument(startOffset, endOffset, suspendConvertedType) // TODO: Should be able to reuse `this` if that is an immutable IrGetValue @@ -452,37 +440,21 @@ internal class AdapterGenerator( } } - private fun findInvokeSymbol(type: IrSimpleType, argument: FirExpression): IrSimpleFunctionSymbol? { + private fun findInvokeSymbol(expectedFunctionalType: ConeClassLikeType, argument: FirExpression): IrSimpleFunctionSymbol? { val argumentType = argument.typeRef.coneType - // Either the argument type is a non-suspend functional type - if (argumentType.isBuiltinFunctionalType(session) && !argumentType.isSuspendFunctionType(session)) { - return (argument.typeRef.coneType as? ConeClassLikeType)?.lookupTag?.classId - ?.let { classId -> - session.firSymbolProvider - .getClassDeclaredCallableSymbols(classId, Name.identifier("invoke")) - .filterIsInstance>() - .find { firFunctionSymbol -> - firFunctionSymbol.fir.valueParameters.size == type.arguments.size - 1 - }?.let { firFunctionSymbol -> - declarationStorage.getIrFunctionSymbol(firFunctionSymbol) as? IrSimpleFunctionSymbol - } - } + // To avoid any remaining exotic types, e.g., intersection type, like it(FunctionN..., SuspendFunctionN...) + if (argumentType !is ConeClassLikeType) { + return null } - // Or is a class-like type whose corresponding class is a user-defined and has an overridden `invoke`. - if (argumentType is ConeClassLikeType) { - val klass = - (session.firSymbolProvider.getClassLikeSymbolByFqName(argumentType.lookupTag.classId) as? FirRegularClassSymbol)?.fir - ?: return null - if (klass.origin != FirDeclarationOrigin.Source) { - return null + if (argumentType.isSubtypeOfFunctionalType(session, expectedFunctionalType)) { + return if (argumentType.isBuiltinFunctionalType(session)) { + argumentType.findBaseInvokeSymbol(session, scopeSession) + } else { + argumentType.findContributedInvokeSymbol(session, scopeSession, expectedFunctionalType) + }?.let { + declarationStorage.getIrFunctionSymbol(it) as? IrSimpleFunctionSymbol } - return klass.declarations - .filterIsInstance() - .singleOrNull { it.name == Name.identifier("invoke") && it.valueParameters.size == type.arguments.size - 1 } - ?.let { invokeFunction -> - declarationStorage.getIrFunctionSymbol(invokeFunction.symbol) as? IrSimpleFunctionSymbol - } } return null diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt index b7c4fb7f42c..4782039bdf2 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt @@ -9,21 +9,15 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference -import org.jetbrains.kotlin.fir.resolve.createFunctionalType -import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isLocalClassOrAnonymousObject -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider -import org.jetbrains.kotlin.fir.resolve.fullyExpandedType +import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.inference.* import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedTypeDeclaration import org.jetbrains.kotlin.fir.returnExpressions import org.jetbrains.kotlin.fir.symbols.StandardClassIds -import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition @@ -228,7 +222,9 @@ fun Candidate.resolvePlainArgumentType( // If the argument is of functional type and the expected type is a suspend function type, we need to do "suspend conversion." if (expectedType != null) { - argumentTypeWithSuspendConversion(session, expectedType, argumentTypeForApplicabilityCheck)?.let { + argumentTypeWithSuspendConversion( + session, context.bodyResolveComponents.scopeSession, expectedType, argumentTypeForApplicabilityCheck + )?.let { argumentTypeForApplicabilityCheck = it substitutor.substituteOrSelf(argumentTypeForApplicabilityCheck) usesSuspendConversion = true @@ -241,44 +237,35 @@ fun Candidate.resolvePlainArgumentType( } private fun argumentTypeWithSuspendConversion( - session: FirSession, expectedType: ConeKotlinType, argumentType: ConeKotlinType + session: FirSession, + scopeSession: ScopeSession, + expectedType: ConeKotlinType, + argumentType: ConeKotlinType ): ConeKotlinType? { // TODO: should refer to LanguageVersionSettings.SuspendConversion - // Expect the expected type to be a suspend functional type. - if (!expectedType.isSuspendFunctionType(session)) { + + // To avoid any remaining exotic types, e.g., intersection type, like it(FunctionN..., SuspendFunctionN...) + if (argumentType !is ConeClassLikeType) { return null } - // Either the argument type is a non-suspend functional type - if (argumentType.isBuiltinFunctionalType(session) && !argumentType.isSuspendFunctionType(session)) { - val typeParameters = argumentType.typeArguments.map { it as ConeKotlinType } - return createFunctionalType( - typeParameters.dropLast(1), null, typeParameters.last(), - isSuspend = true, - isKFunctionType = argumentType.isKFunctionType(session) - ) + // Expect the expected type to be a suspend functional type, and the argument type is not a suspend functional type. + if (!expectedType.isSuspendFunctionType(session) || argumentType.isSuspendFunctionType(session)) { + return null } - // Or is a class-like type whose corresponding class is a user-defined and has an overridden `invoke`. - if (argumentType is ConeClassLikeType) { - val klass = - (session.firSymbolProvider.getClassLikeSymbolByFqName(argumentType.lookupTag.classId) as? FirRegularClassSymbol)?.fir - ?: return null - if (klass.origin != FirDeclarationOrigin.Source) { - return null + // We want to check the argument type against non-suspend functional type. + val expectedFunctionalType = expectedType.suspendFunctionTypeToFunctionType(session) + if (argumentType.isSubtypeOfFunctionalType(session, expectedFunctionalType)) { + return argumentType.findContributedInvokeSymbol(session, scopeSession, expectedFunctionalType)?.let { invokeSymbol -> + createFunctionalType( + invokeSymbol.fir.valueParameters.map { it.returnTypeRef.coneType }, + null, + invokeSymbol.fir.returnTypeRef.coneType, + isSuspend = true, + isKFunctionType = argumentType.isKFunctionType(session) + ) } - return klass.declarations - .filterIsInstance() - .singleOrNull { it.name == Name.identifier("invoke") && it.valueParameters.size == expectedType.typeArguments.size - 1 } - ?.let { invokeFunction -> - createFunctionalType( - invokeFunction.valueParameters.map { it.returnTypeRef.coneType }, - null, - invokeFunction.returnTypeRef.coneType, - isSuspend = true, - isKFunctionType = false - ) - } } return null diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt index 56c10cf8da7..4c0375a37b9 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt @@ -8,10 +8,20 @@ package org.jetbrains.kotlin.fir.resolve.inference import org.jetbrains.kotlin.builtins.functions.FunctionClassKind import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction -import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents +import org.jetbrains.kotlin.fir.declarations.FirClass +import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.Candidate -import org.jetbrains.kotlin.fir.resolve.fullyExpandedType +import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions +import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope +import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl +import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol +import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.types.AbstractTypeChecker +import org.jetbrains.kotlin.util.OperatorNameConventions import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract @@ -45,6 +55,72 @@ fun ConeKotlinType.isKFunctionType(session: FirSession): Boolean { kind == FunctionClassKind.KSuspendFunction } +fun ConeKotlinType.kFunctionTypeToFunctionType(session: FirSession): ConeClassLikeType { + require(this.isKFunctionType(session)) + val kind = + if (isSuspendFunctionType(session)) FunctionClassKind.SuspendFunction + else FunctionClassKind.Function + val functionalTypeId = ClassId(kind.packageFqName, kind.numberedClassName(typeArguments.size - 1)) + return ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(functionalTypeId), typeArguments, isNullable = false) +} + +fun ConeKotlinType.suspendFunctionTypeToFunctionType(session: FirSession): ConeClassLikeType { + require(this.isSuspendFunctionType(session)) + val kind = + if (isKFunctionType(session)) FunctionClassKind.KFunction + else FunctionClassKind.Function + val functionalTypeId = ClassId(kind.packageFqName, kind.numberedClassName(typeArguments.size - 1)) + return ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(functionalTypeId), typeArguments, isNullable = false) +} + +fun ConeKotlinType.isSubtypeOfFunctionalType(session: FirSession, expectedFunctionalType: ConeClassLikeType): Boolean { + require(expectedFunctionalType.isBuiltinFunctionalType(session)) + return AbstractTypeChecker.isSubtypeOf(session.typeContext, this, expectedFunctionalType.replaceArgumentsWithStarProjections()) +} + +fun ConeClassLikeType.findBaseInvokeSymbol(session: FirSession, scopeSession: ScopeSession): FirFunctionSymbol<*>? { + require(this.isBuiltinFunctionalType(session)) + val functionN = (lookupTag.toSymbol(session)?.fir as? FirClass<*>) ?: return null + var baseInvokeSymbol: FirFunctionSymbol<*>? = null + functionN.unsubstitutedScope(session, scopeSession).processFunctionsByName(OperatorNameConventions.INVOKE) { functionSymbol -> + baseInvokeSymbol = functionSymbol + return@processFunctionsByName + } + return baseInvokeSymbol +} + +fun ConeKotlinType.findContributedInvokeSymbol( + session: FirSession, + scopeSession: ScopeSession, + expectedFunctionalType: ConeClassLikeType +): FirFunctionSymbol<*>? { + val baseInvokeSymbol = expectedFunctionalType.findBaseInvokeSymbol(session, scopeSession) ?: return null + + val scope = scope(session, scopeSession) ?: return null + var declaredInvoke: FirFunctionSymbol<*>? = null + scope.processFunctionsByName(OperatorNameConventions.INVOKE) { functionSymbol -> + if (functionSymbol.fir.valueParameters.size == baseInvokeSymbol.fir.valueParameters.size) { + declaredInvoke = functionSymbol + return@processFunctionsByName + } + } + + var overriddenInvoke: FirFunctionSymbol<*>? = null + if (declaredInvoke != null) { + // Make sure the user-contributed or type-substituted invoke we just found above is an override of base invoke. + scope.processOverriddenFunctions(declaredInvoke!!) { functionSymbol -> + if (functionSymbol == baseInvokeSymbol || functionSymbol.overriddenSymbol == baseInvokeSymbol) { + overriddenInvoke = functionSymbol + ProcessorAction.STOP + } else { + ProcessorAction.NEXT + } + } + } + + return if (overriddenInvoke != null) declaredInvoke else null +} + fun ConeKotlinType.receiverType(expectedTypeRef: FirTypeRef?, session: FirSession): ConeKotlinType? { if (isBuiltinFunctionalType(session) && isExtensionFunctionType(session)) { return (this.fullyExpandedType(session).typeArguments.first() as ConeKotlinTypeProjection).type diff --git a/compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt b/compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt index 668a6291477..7466a0ee752 100644 --- a/compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt +++ b/compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt @@ -15,12 +15,17 @@ fun builder(c: suspend () -> Unit) { suspend fun useSuspendFun(fn : suspend () -> String) = fn() suspend fun useSuspendFunInt(fn: suspend (Int) -> String) = fn(42) +suspend fun useSuspendFunStringString(fn: suspend (String, String) -> String) = fn("O", "K") -class Test : () -> String, (Int) -> String { +open class Test : () -> String, (Int) -> String { override fun invoke(): String = "OKEmpty" override fun invoke(p: Int) = "OK$p" } +class Sub : Test(), (String, String) -> String { + override fun invoke(p1: String, p2: String) = p1 + p2 +} + fun box(): String { var test = "Failed" builder { @@ -30,10 +35,14 @@ fun box(): String { if (test != "OKEmpty") return "failed 1" builder { - test = useSuspendFunInt(Test()) + test = useSuspendFunInt(Sub()) } if (test != "OK42") return "failed 2" - return "OK" + builder { + test = useSuspendFunStringString(Sub()) + } + + return test } \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.fir.txt b/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.fir.txt index 3b4ee75964b..793f923c387 100644 --- a/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.fir.txt +++ b/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.fir.txt @@ -51,10 +51,10 @@ FILE fqName: fileName:/suspendConversionOnArbitraryExpression.kt VALUE_PARAMETER name:fn index:0 type:@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1 BLOCK_BODY CALL 'public final fun useSuspendExt (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1): kotlin.Unit declared in ' type=kotlin.Unit origin=null - sfn: BLOCK type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1 [val] GET_VAR 'fn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1 declared in .testExtAsExt' type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1 origin=null - FUN_EXPR type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Unit [suspend] VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:kotlin.Int BLOCK_BODY @@ -79,10 +79,10 @@ FILE fqName: fileName:/suspendConversionOnArbitraryExpression.kt VALUE_PARAMETER name:fn index:0 type:kotlin.Function1 BLOCK_BODY CALL 'public final fun useSuspendExt (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1): kotlin.Unit declared in ' type=kotlin.Unit origin=null - sfn: BLOCK type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION VAR IR_TEMPORARY_VARIABLE name:tmp_4 type:kotlin.Function1 [val] GET_VAR 'fn: kotlin.Function1 declared in .testSimpleAsExt' type=kotlin.Function1 origin=null - FUN_EXPR type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Unit [suspend] VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:kotlin.Int BLOCK_BODY @@ -109,10 +109,10 @@ FILE fqName: fileName:/suspendConversionOnArbitraryExpression.kt BLOCK_BODY CALL 'public final fun useSuspendExtT (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit>): kotlin.Unit declared in ' type=kotlin.Unit origin=null : kotlin.Int - sfn: BLOCK type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION + sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION VAR IR_TEMPORARY_VARIABLE name:tmp_6 type:kotlin.Function1 [val] GET_VAR 'fn: kotlin.Function1 declared in .testSimpleAsExtT' type=kotlin.Function1 origin=null - FUN_EXPR type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION + FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> (p0:T of .useSuspendExtT) returnType:kotlin.Unit [suspend] VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:T of .useSuspendExtT BLOCK_BODY @@ -139,10 +139,10 @@ FILE fqName: fileName:/suspendConversionOnArbitraryExpression.kt BLOCK_BODY CALL 'public final fun useSuspendExtT (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit>): kotlin.Unit declared in ' type=kotlin.Unit origin=null : kotlin.Int - sfn: BLOCK type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION + sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION VAR IR_TEMPORARY_VARIABLE name:tmp_8 type:@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1 [val] GET_VAR 'fn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1 declared in .testExtAsExtT' type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1 origin=null - FUN_EXPR type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION + FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> (p0:T of .useSuspendExtT) returnType:kotlin.Unit [suspend] VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:T of .useSuspendExtT BLOCK_BODY @@ -171,10 +171,10 @@ FILE fqName: fileName:/suspendConversionOnArbitraryExpression.kt BLOCK_BODY CALL 'public final fun useSuspendExtT (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit>): kotlin.Unit declared in ' type=kotlin.Unit origin=null : S of .testSimpleSAsExtT - sfn: BLOCK type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION + sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION VAR IR_TEMPORARY_VARIABLE name:tmp_10 type:kotlin.Function1.testSimpleSAsExtT, kotlin.Unit> [val] GET_VAR 'fn: kotlin.Function1.testSimpleSAsExtT, kotlin.Unit> declared in .testSimpleSAsExtT' type=kotlin.Function1.testSimpleSAsExtT, kotlin.Unit> origin=null - FUN_EXPR type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION + FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> (p0:T of .useSuspendExtT) returnType:kotlin.Unit [suspend] VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:T of .useSuspendExtT BLOCK_BODY @@ -203,10 +203,10 @@ FILE fqName: fileName:/suspendConversionOnArbitraryExpression.kt BLOCK_BODY CALL 'public final fun useSuspendExtT (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit>): kotlin.Unit declared in ' type=kotlin.Unit origin=null : S of .testExtSAsExtT - sfn: BLOCK type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION + sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION VAR IR_TEMPORARY_VARIABLE name:tmp_12 type:@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1.testExtSAsExtT, kotlin.Unit> [val] GET_VAR 'fn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1.testExtSAsExtT, kotlin.Unit> declared in .testExtSAsExtT' type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1.testExtSAsExtT, kotlin.Unit> origin=null - FUN_EXPR type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION + FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> (p0:T of .useSuspendExtT) returnType:kotlin.Unit [suspend] VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:T of .useSuspendExtT BLOCK_BODY