@@ -1468,14 +1468,22 @@ open class KotlinFileExtractor(
14681468 val extractionMethod = if (isFunctionInvoke) {
14691469 // For `kotlin.FunctionX` and `kotlin.reflect.KFunctionX` interfaces, we're making sure that we
14701470 // extract the call to the `invoke` method that does exist, `kotlin.jvm.functions.FunctionX::invoke`.
1471- val interfaceType = getFunctionalInterfaceTypeWithTypeArgs(drType.arguments).classOrNull!! .owner
1472- val substituted = getJavaEquivalentClass(interfaceType) ? : interfaceType
1473- findFunction(substituted, OperatorNameConventions .INVOKE .asString())!!
1471+ val functionalInterface = getFunctionalInterfaceTypeWithTypeArgs(drType.arguments)
1472+ if (functionalInterface == null ) {
1473+ logger.warn(" Cannot find functional interface type for raw method access" )
1474+ null
1475+ } else {
1476+ val interfaceType = functionalInterface.classOrNull!! .owner
1477+ val substituted = getJavaEquivalentClass(interfaceType) ? : interfaceType
1478+ findFunction(substituted, OperatorNameConventions .INVOKE .asString())!!
1479+ }
14741480 } else {
14751481 callTarget
14761482 }
14771483
1478- if (isBigArityFunctionInvoke) {
1484+ if (extractionMethod == null ) {
1485+ null
1486+ } else if (isBigArityFunctionInvoke) {
14791487 // Big arity `invoke` methods have a special implementation on JVM, they are transformed to a call to
14801488 // `kotlin.jvm.functions.FunctionN<out R>::invoke(vararg args: Any?)`, so we only need to pass the type
14811489 // argument for the return type. Additionally, the arguments are extracted inside an array literal below.
@@ -1484,10 +1492,15 @@ open class KotlinFileExtractor(
14841492 useFunction<DbCallable >(extractionMethod, getDeclaringTypeArguments(callTarget, drType))
14851493 }
14861494 }
1487- else
1495+ else {
14881496 useFunction<DbCallable >(callTarget)
1497+ }
14891498
1490- tw.writeCallableBinding(id, methodId)
1499+ if (methodId == null ) {
1500+ logger.warn(" No method to bind call to for raw method access" )
1501+ } else {
1502+ tw.writeCallableBinding(id, methodId)
1503+ }
14911504
14921505 if (callTarget.shouldExtractAsStatic) {
14931506 extractStaticTypeAccessQualifier(callTarget, id, locId, enclosingCallable, enclosingStmt)
@@ -3021,11 +3034,6 @@ open class KotlinFileExtractor(
30213034 var types = parameters.map { it.type }
30223035 types + = e.function.returnType
30233036
3024- val fnInterfaceType = getFunctionalInterfaceType(types)
3025- val id = extractGeneratedClass(
3026- e.function, // We're adding this function as a member, and changing its name to `invoke` to implement `kotlin.FunctionX<,,,>.invoke(,,)`
3027- listOf (pluginContext.irBuiltIns.anyType, fnInterfaceType))
3028-
30293037 val isBigArity = types.size > BuiltInFunctionArity .BIG_ARITY
30303038 if (isBigArity) {
30313039 implementFunctionNInvoke(e.function, ids, locId, parameters)
@@ -3042,12 +3050,21 @@ open class KotlinFileExtractor(
30423050 tw.writeStatementEnclosingExpr(idLambdaExpr, exprParent.enclosingStmt)
30433051 tw.writeCallableBinding(idLambdaExpr, ids.constructor )
30443052
3045- extractTypeAccessRecursive(fnInterfaceType, locId, idLambdaExpr, - 3 , callable, exprParent.enclosingStmt)
3046-
30473053 // todo: fix hard coded block body of lambda
30483054 tw.writeLambdaKind(idLambdaExpr, 1 )
30493055
3050- tw.writeIsAnonymClass(id, idLambdaExpr)
3056+ val fnInterfaceType = getFunctionalInterfaceType(types)
3057+ if (fnInterfaceType == null ) {
3058+ logger.warnElement(" Cannot find functional interface type for function expression" , e)
3059+ } else {
3060+ val id = extractGeneratedClass(
3061+ e.function, // We're adding this function as a member, and changing its name to `invoke` to implement `kotlin.FunctionX<,,,>.invoke(,,)`
3062+ listOf (pluginContext.irBuiltIns.anyType, fnInterfaceType))
3063+
3064+ extractTypeAccessRecursive(fnInterfaceType, locId, idLambdaExpr, - 3 , callable, exprParent.enclosingStmt)
3065+
3066+ tw.writeIsAnonymClass(id, idLambdaExpr)
3067+ }
30513068 }
30523069 is IrClassReference -> {
30533070 val exprParent = parent.expr(e, callable)
@@ -3737,7 +3754,6 @@ open class KotlinFileExtractor(
37373754 dispatchReceiverIdx = - 1
37383755 }
37393756
3740- val targetCallableId = useFunction<DbCallable >(target.owner.realOverrideTarget, classTypeArguments)
37413757 val locId = tw.getLocation(functionReferenceExpr)
37423758
37433759 val javaResult = TypeResult (tw.getFreshIdLabel<DbClass >(), " " , " " )
@@ -3750,36 +3766,6 @@ open class KotlinFileExtractor(
37503766 constructorBlock = tw.getFreshIdLabel()
37513767 )
37523768
3753- val helper = CallableReferenceHelper (functionReferenceExpr, locId, ids)
3754-
3755- val fnInterfaceType = getFunctionalInterfaceTypeWithTypeArgs(type.arguments)
3756-
3757- val currentDeclaration = declarationStack.peek()
3758- // `FunctionReference` base class is required, because that's implementing `KFunction`.
3759- val baseClass = pluginContext.referenceClass(FqName (" kotlin.jvm.internal.FunctionReference" ))?.owner?.typeWith()
3760- ? : pluginContext.irBuiltIns.anyType
3761-
3762- val classId = extractGeneratedClass(ids, listOf (baseClass, fnInterfaceType), locId, currentDeclaration)
3763-
3764- helper.extractReceiverField()
3765-
3766- val isBigArity = type.arguments.size > BuiltInFunctionArity .BIG_ARITY
3767- val funLabels = if (isBigArity) {
3768- addFunctionNInvoke(ids.function, parameterTypes.last(), classId, locId)
3769- } else {
3770- addFunctionInvoke(ids.function, parameterTypes.dropLast(1 ), parameterTypes.last(), classId, locId)
3771- }
3772-
3773- helper.extractCallToReflectionTarget(
3774- funLabels,
3775- target,
3776- parameterTypes.last(),
3777- expressionTypeArguments,
3778- classTypeArguments,
3779- dispatchReceiverIdx,
3780- isBigArity,
3781- parameterTypes.dropLast(1 ))
3782-
37833769 // Add constructor (member ref) call:
37843770 val exprParent = parent.expr(functionReferenceExpr, callable)
37853771 val idMemberRef = tw.getFreshIdLabel<DbMemberref >()
@@ -3790,40 +3776,87 @@ open class KotlinFileExtractor(
37903776 tw.writeStatementEnclosingExpr(idMemberRef, exprParent.enclosingStmt)
37913777 tw.writeCallableBinding(idMemberRef, ids.constructor )
37923778
3793- val typeAccessArguments = if (isBigArity) listOf (parameterTypes.last()) else parameterTypes
3794- if (target is IrConstructorSymbol ) {
3795- val returnType = typeAccessArguments.last()
3779+ val targetCallableId = useFunction<DbCallable >(target.owner.realOverrideTarget, classTypeArguments)
3780+ tw.writeMemberRefBinding(idMemberRef, targetCallableId)
37963781
3797- val typeAccessId = extractTypeAccess(useType(fnInterfaceType, TypeContext .OTHER ), locId, idMemberRef, - 3 , callable, exprParent.enclosingStmt)
3798- typeAccessArguments.dropLast(1 ).forEachIndexed { argIdx, arg ->
3799- extractTypeAccessRecursive(arg, locId, typeAccessId, argIdx, callable, exprParent.enclosingStmt, TypeContext .GENERIC_ARGUMENT )
3800- }
3782+ val helper = CallableReferenceHelper (functionReferenceExpr, locId, ids)
38013783
3802- extractConstructorTypeAccess(returnType, useType(returnType), target, locId, typeAccessId, typeAccessArguments.count() - 1 , callable, exprParent.enclosingStmt)
3784+ val fnInterfaceType = getFunctionalInterfaceTypeWithTypeArgs(type.arguments)
3785+ if (fnInterfaceType == null ) {
3786+ logger.warnElement(" Cannot find functional interface type for function reference" , functionReferenceExpr)
38033787 } else {
3804- extractTypeAccessRecursive(fnInterfaceType, locId, idMemberRef, - 3 , callable, exprParent.enclosingStmt)
3805- }
3788+ val currentDeclaration = declarationStack.peek()
3789+ // `FunctionReference` base class is required, because that's implementing `KFunction`.
3790+ val baseClass = pluginContext.referenceClass(FqName (" kotlin.jvm.internal.FunctionReference" ))?.owner?.typeWith()
3791+ ? : pluginContext.irBuiltIns.anyType
38063792
3807- tw.writeMemberRefBinding(idMemberRef, targetCallableId)
3793+ val classId = extractGeneratedClass(ids, listOf (baseClass, fnInterfaceType), locId, currentDeclaration)
3794+
3795+ helper.extractReceiverField()
3796+
3797+ val isBigArity = type.arguments.size > BuiltInFunctionArity .BIG_ARITY
3798+ val funLabels = if (isBigArity) {
3799+ addFunctionNInvoke(ids.function, parameterTypes.last(), classId, locId)
3800+ } else {
3801+ addFunctionInvoke(ids.function, parameterTypes.dropLast(1 ), parameterTypes.last(), classId, locId)
3802+ }
3803+
3804+ helper.extractCallToReflectionTarget(
3805+ funLabels,
3806+ target,
3807+ parameterTypes.last(),
3808+ expressionTypeArguments,
3809+ classTypeArguments,
3810+ dispatchReceiverIdx,
3811+ isBigArity,
3812+ parameterTypes.dropLast(1 ))
3813+
3814+ val typeAccessArguments = if (isBigArity) listOf (parameterTypes.last()) else parameterTypes
3815+ if (target is IrConstructorSymbol ) {
3816+ val returnType = typeAccessArguments.last()
3817+
3818+ val typeAccessId = extractTypeAccess(useType(fnInterfaceType, TypeContext .OTHER ), locId, idMemberRef, - 3 , callable, exprParent.enclosingStmt)
3819+ typeAccessArguments.dropLast(1 ).forEachIndexed { argIdx, arg ->
3820+ extractTypeAccessRecursive(arg, locId, typeAccessId, argIdx, callable, exprParent.enclosingStmt, TypeContext .GENERIC_ARGUMENT )
3821+ }
3822+
3823+ extractConstructorTypeAccess(returnType, useType(returnType), target, locId, typeAccessId, typeAccessArguments.count() - 1 , callable, exprParent.enclosingStmt)
3824+ } else {
3825+ extractTypeAccessRecursive(fnInterfaceType, locId, idMemberRef, - 3 , callable, exprParent.enclosingStmt)
3826+ }
38083827
3809- helper.extractConstructorArguments(callable, idMemberRef, exprParent.enclosingStmt)
3828+ helper.extractConstructorArguments(callable, idMemberRef, exprParent.enclosingStmt)
38103829
3811- tw.writeIsAnonymClass(classId, idMemberRef)
3830+ tw.writeIsAnonymClass(classId, idMemberRef)
3831+ }
38123832 }
38133833 }
38143834
3815- private fun getFunctionalInterfaceType (functionNTypeArguments : List <IrType >) =
3835+ private fun getFunctionalInterfaceType (functionNTypeArguments : List <IrType >): IrSimpleType ? {
38163836 if (functionNTypeArguments.size > BuiltInFunctionArity .BIG_ARITY ) {
3817- pluginContext.referenceClass(FqName (" kotlin.jvm.functions.FunctionN" ))!!
3818- .typeWith(functionNTypeArguments.last())
3837+ val funName = " kotlin.jvm.functions.FunctionN"
3838+ val theFun = pluginContext.referenceClass(FqName (funName))
3839+ if (theFun == null ) {
3840+ logger.warn(" Cannot find $funName for getFunctionalInterfaceType" )
3841+ return null
3842+ } else {
3843+ return theFun.typeWith(functionNTypeArguments.last())
3844+ }
38193845 } else {
3820- functionN(pluginContext)(functionNTypeArguments.size - 1 ).typeWith(functionNTypeArguments)
3846+ return functionN(pluginContext)(functionNTypeArguments.size - 1 ).typeWith(functionNTypeArguments)
38213847 }
3848+ }
38223849
3823- private fun getFunctionalInterfaceTypeWithTypeArgs (functionNTypeArguments : List <IrTypeArgument >) =
3850+ private fun getFunctionalInterfaceTypeWithTypeArgs (functionNTypeArguments : List <IrTypeArgument >): IrSimpleType ? =
38243851 if (functionNTypeArguments.size > BuiltInFunctionArity .BIG_ARITY ) {
3825- pluginContext.referenceClass(FqName (" kotlin.jvm.functions.FunctionN" ))!!
3826- .typeWithArguments(listOf (functionNTypeArguments.last()))
3852+ val funName = " kotlin.jvm.functions.FunctionN"
3853+ val theFun = pluginContext.referenceClass(FqName (funName))
3854+ if (theFun == null ) {
3855+ logger.warn(" Cannot find $funName for getFunctionalInterfaceTypeWithTypeArgs" )
3856+ null
3857+ } else {
3858+ theFun.typeWithArguments(listOf (functionNTypeArguments.last()))
3859+ }
38273860 } else {
38283861 functionN(pluginContext)(functionNTypeArguments.size - 1 ).symbol.typeWithArguments(functionNTypeArguments)
38293862 }
@@ -4321,6 +4354,10 @@ open class KotlinFileExtractor(
43214354
43224355 // Either Function1, ... Function22 or FunctionN type, but not Function23 or above.
43234356 val functionType = getFunctionalInterfaceTypeWithTypeArgs(st.arguments)
4357+ if (functionType == null ) {
4358+ logger.errorElement(" Cannot find functional interface." , e)
4359+ return
4360+ }
43244361
43254362 val invokeMethod = functionType.classOrNull?.owner?.declarations?.filterIsInstance<IrFunction >()?.find { it.name.asString() == OperatorNameConventions .INVOKE .asString()}
43264363 if (invokeMethod == null ) {
0 commit comments