FIR: utilize checking subtype of functional type and finding invoke symbol
This commit is contained in:
committed by
Denis Zharkov
parent
b10466f6a2
commit
5b136516c4
+21
-49
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.backend.generators
|
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.DescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.fir.backend.*
|
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.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||||
import org.jetbrains.kotlin.fir.render
|
import org.jetbrains.kotlin.fir.render
|
||||||
import org.jetbrains.kotlin.fir.resolve.createFunctionalType
|
import org.jetbrains.kotlin.fir.resolve.inference.*
|
||||||
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.symbols.impl.FirFunctionSymbol
|
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.ConeClassLikeType
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
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.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
|
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.isUnit
|
||||||
import org.jetbrains.kotlin.ir.types.typeOrNull
|
import org.jetbrains.kotlin.ir.types.typeOrNull
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.utils.SmartList
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
|
|
||||||
@@ -129,14 +120,8 @@ internal class AdapterGenerator(
|
|||||||
return hasSpreadCase
|
return hasSpreadCase
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun ConeKotlinType.kFunctionTypeToFunctionType(): IrSimpleType {
|
internal fun ConeKotlinType.kFunctionTypeToFunctionType(): IrSimpleType =
|
||||||
val kind =
|
kFunctionTypeToFunctionType(session).toIrType() as IrSimpleType
|
||||||
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 generateAdaptedCallableReference(
|
internal fun generateAdaptedCallableReference(
|
||||||
callableReferenceAccess: FirCallableReferenceAccess,
|
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.
|
* 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 {
|
* class Foo {
|
||||||
* override fun invoke() = ...
|
* override fun invoke() = ...
|
||||||
* }
|
* }
|
||||||
@@ -421,13 +406,16 @@ internal class AdapterGenerator(
|
|||||||
if (this is IrBlock && origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE) {
|
if (this is IrBlock && origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE) {
|
||||||
return this
|
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
|
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 returnType = suspendConvertedType.arguments.last().typeOrNull!!
|
||||||
val invokeSymbol = findInvokeSymbol(suspendConvertedType, argument) ?: return this
|
|
||||||
return argument.convertWithOffsets { startOffset, endOffset ->
|
return argument.convertWithOffsets { startOffset, endOffset ->
|
||||||
val irAdapterFunction = createAdapterFunctionForArgument(startOffset, endOffset, suspendConvertedType)
|
val irAdapterFunction = createAdapterFunctionForArgument(startOffset, endOffset, suspendConvertedType)
|
||||||
// TODO: Should be able to reuse `this` if that is an immutable IrGetValue
|
// 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
|
val argumentType = argument.typeRef.coneType
|
||||||
// Either the argument type is a non-suspend functional type
|
// To avoid any remaining exotic types, e.g., intersection type, like it(FunctionN..., SuspendFunctionN...)
|
||||||
if (argumentType.isBuiltinFunctionalType(session) && !argumentType.isSuspendFunctionType(session)) {
|
if (argumentType !is ConeClassLikeType) {
|
||||||
return (argument.typeRef.coneType as? ConeClassLikeType)?.lookupTag?.classId
|
return null
|
||||||
?.let { classId ->
|
|
||||||
session.firSymbolProvider
|
|
||||||
.getClassDeclaredCallableSymbols(classId, Name.identifier("invoke"))
|
|
||||||
.filterIsInstance<FirFunctionSymbol<*>>()
|
|
||||||
.find { firFunctionSymbol ->
|
|
||||||
firFunctionSymbol.fir.valueParameters.size == type.arguments.size - 1
|
|
||||||
}?.let { firFunctionSymbol ->
|
|
||||||
declarationStorage.getIrFunctionSymbol(firFunctionSymbol) as? IrSimpleFunctionSymbol
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Or is a class-like type whose corresponding class is a user-defined and has an overridden `invoke`.
|
if (argumentType.isSubtypeOfFunctionalType(session, expectedFunctionalType)) {
|
||||||
if (argumentType is ConeClassLikeType) {
|
return if (argumentType.isBuiltinFunctionalType(session)) {
|
||||||
val klass =
|
argumentType.findBaseInvokeSymbol(session, scopeSession)
|
||||||
(session.firSymbolProvider.getClassLikeSymbolByFqName(argumentType.lookupTag.classId) as? FirRegularClassSymbol)?.fir
|
} else {
|
||||||
?: return null
|
argumentType.findContributedInvokeSymbol(session, scopeSession, expectedFunctionalType)
|
||||||
if (klass.origin != FirDeclarationOrigin.Source) {
|
}?.let {
|
||||||
return null
|
declarationStorage.getIrFunctionSymbol(it) as? IrSimpleFunctionSymbol
|
||||||
}
|
}
|
||||||
return klass.declarations
|
|
||||||
.filterIsInstance<FirSimpleFunction>()
|
|
||||||
.singleOrNull { it.name == Name.identifier("invoke") && it.valueParameters.size == type.arguments.size - 1 }
|
|
||||||
?.let { invokeFunction ->
|
|
||||||
declarationStorage.getIrFunctionSymbol(invokeFunction.symbol) as? IrSimpleFunctionSymbol
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -9,21 +9,15 @@ import org.jetbrains.kotlin.fir.FirSession
|
|||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.createFunctionalType
|
import org.jetbrains.kotlin.fir.resolve.*
|
||||||
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.inference.*
|
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.firUnsafe
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedTypeDeclaration
|
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedTypeDeclaration
|
||||||
import org.jetbrains.kotlin.fir.returnExpressions
|
import org.jetbrains.kotlin.fir.returnExpressions
|
||||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
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.typeContext
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
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.ConstraintSystemBuilder
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
|
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
|
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 the argument is of functional type and the expected type is a suspend function type, we need to do "suspend conversion."
|
||||||
if (expectedType != null) {
|
if (expectedType != null) {
|
||||||
argumentTypeWithSuspendConversion(session, expectedType, argumentTypeForApplicabilityCheck)?.let {
|
argumentTypeWithSuspendConversion(
|
||||||
|
session, context.bodyResolveComponents.scopeSession, expectedType, argumentTypeForApplicabilityCheck
|
||||||
|
)?.let {
|
||||||
argumentTypeForApplicabilityCheck = it
|
argumentTypeForApplicabilityCheck = it
|
||||||
substitutor.substituteOrSelf(argumentTypeForApplicabilityCheck)
|
substitutor.substituteOrSelf(argumentTypeForApplicabilityCheck)
|
||||||
usesSuspendConversion = true
|
usesSuspendConversion = true
|
||||||
@@ -241,44 +237,35 @@ fun Candidate.resolvePlainArgumentType(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun argumentTypeWithSuspendConversion(
|
private fun argumentTypeWithSuspendConversion(
|
||||||
session: FirSession, expectedType: ConeKotlinType, argumentType: ConeKotlinType
|
session: FirSession,
|
||||||
|
scopeSession: ScopeSession,
|
||||||
|
expectedType: ConeKotlinType,
|
||||||
|
argumentType: ConeKotlinType
|
||||||
): ConeKotlinType? {
|
): ConeKotlinType? {
|
||||||
// TODO: should refer to LanguageVersionSettings.SuspendConversion
|
// 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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Either the argument type is a non-suspend functional type
|
// Expect the expected type to be a suspend functional type, and the argument type is not a suspend functional type.
|
||||||
if (argumentType.isBuiltinFunctionalType(session) && !argumentType.isSuspendFunctionType(session)) {
|
if (!expectedType.isSuspendFunctionType(session) || argumentType.isSuspendFunctionType(session)) {
|
||||||
val typeParameters = argumentType.typeArguments.map { it as ConeKotlinType }
|
return null
|
||||||
return createFunctionalType(
|
|
||||||
typeParameters.dropLast(1), null, typeParameters.last(),
|
|
||||||
isSuspend = true,
|
|
||||||
isKFunctionType = argumentType.isKFunctionType(session)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Or is a class-like type whose corresponding class is a user-defined and has an overridden `invoke`.
|
// We want to check the argument type against non-suspend functional type.
|
||||||
if (argumentType is ConeClassLikeType) {
|
val expectedFunctionalType = expectedType.suspendFunctionTypeToFunctionType(session)
|
||||||
val klass =
|
if (argumentType.isSubtypeOfFunctionalType(session, expectedFunctionalType)) {
|
||||||
(session.firSymbolProvider.getClassLikeSymbolByFqName(argumentType.lookupTag.classId) as? FirRegularClassSymbol)?.fir
|
return argumentType.findContributedInvokeSymbol(session, scopeSession, expectedFunctionalType)?.let { invokeSymbol ->
|
||||||
?: return null
|
createFunctionalType(
|
||||||
if (klass.origin != FirDeclarationOrigin.Source) {
|
invokeSymbol.fir.valueParameters.map { it.returnTypeRef.coneType },
|
||||||
return null
|
null,
|
||||||
|
invokeSymbol.fir.returnTypeRef.coneType,
|
||||||
|
isSuspend = true,
|
||||||
|
isKFunctionType = argumentType.isKFunctionType(session)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return klass.declarations
|
|
||||||
.filterIsInstance<FirSimpleFunction>()
|
|
||||||
.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
|
return null
|
||||||
|
|||||||
+78
-2
@@ -8,10 +8,20 @@ package org.jetbrains.kotlin.fir.resolve.inference
|
|||||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
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.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.*
|
||||||
|
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.ExperimentalContracts
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
@@ -45,6 +55,72 @@ fun ConeKotlinType.isKFunctionType(session: FirSession): Boolean {
|
|||||||
kind == FunctionClassKind.KSuspendFunction
|
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? {
|
fun ConeKotlinType.receiverType(expectedTypeRef: FirTypeRef?, session: FirSession): ConeKotlinType? {
|
||||||
if (isBuiltinFunctionalType(session) && isExtensionFunctionType(session)) {
|
if (isBuiltinFunctionalType(session) && isExtensionFunctionType(session)) {
|
||||||
return (this.fullyExpandedType(session).typeArguments.first() as ConeKotlinTypeProjection).type
|
return (this.fullyExpandedType(session).typeArguments.first() as ConeKotlinTypeProjection).type
|
||||||
|
|||||||
+12
-3
@@ -15,12 +15,17 @@ fun builder(c: suspend () -> Unit) {
|
|||||||
|
|
||||||
suspend fun useSuspendFun(fn : suspend () -> String) = fn()
|
suspend fun useSuspendFun(fn : suspend () -> String) = fn()
|
||||||
suspend fun useSuspendFunInt(fn: suspend (Int) -> String) = fn(42)
|
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(): String = "OKEmpty"
|
||||||
override fun invoke(p: Int) = "OK$p"
|
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 {
|
fun box(): String {
|
||||||
var test = "Failed"
|
var test = "Failed"
|
||||||
builder {
|
builder {
|
||||||
@@ -30,10 +35,14 @@ fun box(): String {
|
|||||||
if (test != "OKEmpty") return "failed 1"
|
if (test != "OKEmpty") return "failed 1"
|
||||||
|
|
||||||
builder {
|
builder {
|
||||||
test = useSuspendFunInt(Test())
|
test = useSuspendFunInt(Sub())
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test != "OK42") return "failed 2"
|
if (test != "OK42") return "failed 2"
|
||||||
|
|
||||||
return "OK"
|
builder {
|
||||||
|
test = useSuspendFunStringString(Sub())
|
||||||
|
}
|
||||||
|
|
||||||
|
return test
|
||||||
}
|
}
|
||||||
+12
-12
@@ -51,10 +51,10 @@ FILE fqName:<root> fileName:/suspendConversionOnArbitraryExpression.kt
|
|||||||
VALUE_PARAMETER name:fn index:0 type:@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<kotlin.Int, kotlin.Unit>
|
VALUE_PARAMETER name:fn index:0 type:@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<kotlin.Int, kotlin.Unit>
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CALL 'public final fun useSuspendExt (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
CALL 'public final fun useSuspendExt (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
sfn: BLOCK type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit> origin=SUSPEND_CONVERSION
|
sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit> origin=SUSPEND_CONVERSION
|
||||||
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<kotlin.Int, kotlin.Unit> [val]
|
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<kotlin.Int, kotlin.Unit> [val]
|
||||||
GET_VAR 'fn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<kotlin.Int, kotlin.Unit> declared in <root>.testExtAsExt' type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
|
GET_VAR 'fn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<kotlin.Int, kotlin.Unit> declared in <root>.testExtAsExt' type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
|
||||||
FUN_EXPR type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit> origin=SUSPEND_CONVERSION
|
FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit> origin=SUSPEND_CONVERSION
|
||||||
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Unit [suspend]
|
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
|
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:kotlin.Int
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
@@ -79,10 +79,10 @@ FILE fqName:<root> fileName:/suspendConversionOnArbitraryExpression.kt
|
|||||||
VALUE_PARAMETER name:fn index:0 type:kotlin.Function1<kotlin.Int, kotlin.Unit>
|
VALUE_PARAMETER name:fn index:0 type:kotlin.Function1<kotlin.Int, kotlin.Unit>
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CALL 'public final fun useSuspendExt (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
CALL 'public final fun useSuspendExt (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
sfn: BLOCK type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit> origin=SUSPEND_CONVERSION
|
sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit> origin=SUSPEND_CONVERSION
|
||||||
VAR IR_TEMPORARY_VARIABLE name:tmp_4 type:kotlin.Function1<kotlin.Int, kotlin.Unit> [val]
|
VAR IR_TEMPORARY_VARIABLE name:tmp_4 type:kotlin.Function1<kotlin.Int, kotlin.Unit> [val]
|
||||||
GET_VAR 'fn: kotlin.Function1<kotlin.Int, kotlin.Unit> declared in <root>.testSimpleAsExt' type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
|
GET_VAR 'fn: kotlin.Function1<kotlin.Int, kotlin.Unit> declared in <root>.testSimpleAsExt' type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
|
||||||
FUN_EXPR type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit> origin=SUSPEND_CONVERSION
|
FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit> origin=SUSPEND_CONVERSION
|
||||||
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Unit [suspend]
|
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
|
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:kotlin.Int
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
@@ -109,10 +109,10 @@ FILE fqName:<root> fileName:/suspendConversionOnArbitraryExpression.kt
|
|||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CALL 'public final fun useSuspendExtT <T> (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
CALL 'public final fun useSuspendExtT <T> (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
<T>: kotlin.Int
|
<T>: kotlin.Int
|
||||||
sfn: BLOCK type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION
|
sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION
|
||||||
VAR IR_TEMPORARY_VARIABLE name:tmp_6 type:kotlin.Function1<kotlin.Int, kotlin.Unit> [val]
|
VAR IR_TEMPORARY_VARIABLE name:tmp_6 type:kotlin.Function1<kotlin.Int, kotlin.Unit> [val]
|
||||||
GET_VAR 'fn: kotlin.Function1<kotlin.Int, kotlin.Unit> declared in <root>.testSimpleAsExtT' type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
|
GET_VAR 'fn: kotlin.Function1<kotlin.Int, kotlin.Unit> declared in <root>.testSimpleAsExtT' type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
|
||||||
FUN_EXPR type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION
|
FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION
|
||||||
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> (p0:T of <root>.useSuspendExtT) returnType:kotlin.Unit [suspend]
|
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> (p0:T of <root>.useSuspendExtT) returnType:kotlin.Unit [suspend]
|
||||||
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:T of <root>.useSuspendExtT
|
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:T of <root>.useSuspendExtT
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
@@ -139,10 +139,10 @@ FILE fqName:<root> fileName:/suspendConversionOnArbitraryExpression.kt
|
|||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CALL 'public final fun useSuspendExtT <T> (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
CALL 'public final fun useSuspendExtT <T> (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
<T>: kotlin.Int
|
<T>: kotlin.Int
|
||||||
sfn: BLOCK type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION
|
sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION
|
||||||
VAR IR_TEMPORARY_VARIABLE name:tmp_8 type:@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<kotlin.Int, kotlin.Unit> [val]
|
VAR IR_TEMPORARY_VARIABLE name:tmp_8 type:@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<kotlin.Int, kotlin.Unit> [val]
|
||||||
GET_VAR 'fn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<kotlin.Int, kotlin.Unit> declared in <root>.testExtAsExtT' type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
|
GET_VAR 'fn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<kotlin.Int, kotlin.Unit> declared in <root>.testExtAsExtT' type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
|
||||||
FUN_EXPR type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION
|
FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION
|
||||||
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> (p0:T of <root>.useSuspendExtT) returnType:kotlin.Unit [suspend]
|
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> (p0:T of <root>.useSuspendExtT) returnType:kotlin.Unit [suspend]
|
||||||
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:T of <root>.useSuspendExtT
|
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:T of <root>.useSuspendExtT
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
@@ -171,10 +171,10 @@ FILE fqName:<root> fileName:/suspendConversionOnArbitraryExpression.kt
|
|||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CALL 'public final fun useSuspendExtT <T> (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
CALL 'public final fun useSuspendExtT <T> (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
<T>: S of <root>.testSimpleSAsExtT
|
<T>: S of <root>.testSimpleSAsExtT
|
||||||
sfn: BLOCK type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION
|
sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION
|
||||||
VAR IR_TEMPORARY_VARIABLE name:tmp_10 type:kotlin.Function1<S of <root>.testSimpleSAsExtT, kotlin.Unit> [val]
|
VAR IR_TEMPORARY_VARIABLE name:tmp_10 type:kotlin.Function1<S of <root>.testSimpleSAsExtT, kotlin.Unit> [val]
|
||||||
GET_VAR 'fn: kotlin.Function1<S of <root>.testSimpleSAsExtT, kotlin.Unit> declared in <root>.testSimpleSAsExtT' type=kotlin.Function1<S of <root>.testSimpleSAsExtT, kotlin.Unit> origin=null
|
GET_VAR 'fn: kotlin.Function1<S of <root>.testSimpleSAsExtT, kotlin.Unit> declared in <root>.testSimpleSAsExtT' type=kotlin.Function1<S of <root>.testSimpleSAsExtT, kotlin.Unit> origin=null
|
||||||
FUN_EXPR type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION
|
FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION
|
||||||
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> (p0:T of <root>.useSuspendExtT) returnType:kotlin.Unit [suspend]
|
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> (p0:T of <root>.useSuspendExtT) returnType:kotlin.Unit [suspend]
|
||||||
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:T of <root>.useSuspendExtT
|
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:T of <root>.useSuspendExtT
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
@@ -203,10 +203,10 @@ FILE fqName:<root> fileName:/suspendConversionOnArbitraryExpression.kt
|
|||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CALL 'public final fun useSuspendExtT <T> (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
CALL 'public final fun useSuspendExtT <T> (sfn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||||
<T>: S of <root>.testExtSAsExtT
|
<T>: S of <root>.testExtSAsExtT
|
||||||
sfn: BLOCK type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION
|
sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION
|
||||||
VAR IR_TEMPORARY_VARIABLE name:tmp_12 type:@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<S of <root>.testExtSAsExtT, kotlin.Unit> [val]
|
VAR IR_TEMPORARY_VARIABLE name:tmp_12 type:@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<S of <root>.testExtSAsExtT, kotlin.Unit> [val]
|
||||||
GET_VAR 'fn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<S of <root>.testExtSAsExtT, kotlin.Unit> declared in <root>.testExtSAsExtT' type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<S of <root>.testExtSAsExtT, kotlin.Unit> origin=null
|
GET_VAR 'fn: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<S of <root>.testExtSAsExtT, kotlin.Unit> declared in <root>.testExtSAsExtT' type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.Function1<S of <root>.testExtSAsExtT, kotlin.Unit> origin=null
|
||||||
FUN_EXPR type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION
|
FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<T of <root>.useSuspendExtT, kotlin.Unit> origin=SUSPEND_CONVERSION
|
||||||
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> (p0:T of <root>.useSuspendExtT) returnType:kotlin.Unit [suspend]
|
FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion visibility:local modality:FINAL <> (p0:T of <root>.useSuspendExtT) returnType:kotlin.Unit [suspend]
|
||||||
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:T of <root>.useSuspendExtT
|
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:T of <root>.useSuspendExtT
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
|
|||||||
Reference in New Issue
Block a user