@@ -1469,14 +1469,22 @@ open class KotlinFileExtractor(
14691469 val extractionMethod = if (isFunctionInvoke) {
14701470 // For `kotlin.FunctionX` and `kotlin.reflect.KFunctionX` interfaces, we're making sure that we
14711471 // extract the call to the `invoke` method that does exist, `kotlin.jvm.functions.FunctionX::invoke`.
1472- val interfaceType = getFunctionalInterfaceTypeWithTypeArgs(drType.arguments).classOrNull!! .owner
1473- val substituted = getJavaEquivalentClass(interfaceType) ? : interfaceType
1474- findFunction(substituted, OperatorNameConventions .INVOKE .asString())!!
1472+ val functionalInterface = getFunctionalInterfaceTypeWithTypeArgs(drType.arguments)
1473+ if (functionalInterface == null ) {
1474+ logger.warn(" Cannot find functional interface type for raw method access" )
1475+ null
1476+ } else {
1477+ val interfaceType = functionalInterface.classOrNull!! .owner
1478+ val substituted = getJavaEquivalentClass(interfaceType) ? : interfaceType
1479+ findFunction(substituted, OperatorNameConventions .INVOKE .asString())!!
1480+ }
14751481 } else {
14761482 callTarget
14771483 }
14781484
1479- if (isBigArityFunctionInvoke) {
1485+ if (extractionMethod == null ) {
1486+ null
1487+ } else if (isBigArityFunctionInvoke) {
14801488 // Big arity `invoke` methods have a special implementation on JVM, they are transformed to a call to
14811489 // `kotlin.jvm.functions.FunctionN<out R>::invoke(vararg args: Any?)`, so we only need to pass the type
14821490 // argument for the return type. Additionally, the arguments are extracted inside an array literal below.
@@ -1485,10 +1493,15 @@ open class KotlinFileExtractor(
14851493 useFunction<DbCallable >(extractionMethod, getDeclaringTypeArguments(callTarget, drType))
14861494 }
14871495 }
1488- else
1496+ else {
14891497 useFunction<DbCallable >(callTarget)
1498+ }
14901499
1491- tw.writeCallableBinding(id, methodId)
1500+ if (methodId == null ) {
1501+ logger.warn(" No method to bind call to for raw method access" )
1502+ } else {
1503+ tw.writeCallableBinding(id, methodId)
1504+ }
14921505
14931506 if (callTarget.shouldExtractAsStatic) {
14941507 extractStaticTypeAccessQualifier(callTarget, id, locId, enclosingCallable, enclosingStmt)
@@ -3022,11 +3035,6 @@ open class KotlinFileExtractor(
30223035 var types = parameters.map { it.type }
30233036 types + = e.function.returnType
30243037
3025- val fnInterfaceType = getFunctionalInterfaceType(types)
3026- val id = extractGeneratedClass(
3027- e.function, // We're adding this function as a member, and changing its name to `invoke` to implement `kotlin.FunctionX<,,,>.invoke(,,)`
3028- listOf (pluginContext.irBuiltIns.anyType, fnInterfaceType))
3029-
30303038 val isBigArity = types.size > BuiltInFunctionArity .BIG_ARITY
30313039 if (isBigArity) {
30323040 implementFunctionNInvoke(e.function, ids, locId, parameters)
@@ -3043,12 +3051,21 @@ open class KotlinFileExtractor(
30433051 tw.writeStatementEnclosingExpr(idLambdaExpr, exprParent.enclosingStmt)
30443052 tw.writeCallableBinding(idLambdaExpr, ids.constructor )
30453053
3046- extractTypeAccessRecursive(fnInterfaceType, locId, idLambdaExpr, - 3 , callable, exprParent.enclosingStmt)
3047-
30483054 // todo: fix hard coded block body of lambda
30493055 tw.writeLambdaKind(idLambdaExpr, 1 )
30503056
3051- tw.writeIsAnonymClass(id, idLambdaExpr)
3057+ val fnInterfaceType = getFunctionalInterfaceType(types)
3058+ if (fnInterfaceType == null ) {
3059+ logger.warnElement(" Cannot find functional interface type for function expression" , e)
3060+ } else {
3061+ val id = extractGeneratedClass(
3062+ e.function, // We're adding this function as a member, and changing its name to `invoke` to implement `kotlin.FunctionX<,,,>.invoke(,,)`
3063+ listOf (pluginContext.irBuiltIns.anyType, fnInterfaceType))
3064+
3065+ extractTypeAccessRecursive(fnInterfaceType, locId, idLambdaExpr, - 3 , callable, exprParent.enclosingStmt)
3066+
3067+ tw.writeIsAnonymClass(id, idLambdaExpr)
3068+ }
30523069 }
30533070 is IrClassReference -> {
30543071 val exprParent = parent.expr(e, callable)
@@ -3738,7 +3755,6 @@ open class KotlinFileExtractor(
37383755 dispatchReceiverIdx = - 1
37393756 }
37403757
3741- val targetCallableId = useFunction<DbCallable >(target.owner.realOverrideTarget, classTypeArguments)
37423758 val locId = tw.getLocation(functionReferenceExpr)
37433759
37443760 val javaResult = TypeResult (tw.getFreshIdLabel<DbClass >(), " " , " " )
@@ -3751,36 +3767,6 @@ open class KotlinFileExtractor(
37513767 constructorBlock = tw.getFreshIdLabel()
37523768 )
37533769
3754- val helper = CallableReferenceHelper (functionReferenceExpr, locId, ids)
3755-
3756- val fnInterfaceType = getFunctionalInterfaceTypeWithTypeArgs(type.arguments)
3757-
3758- val currentDeclaration = declarationStack.peek()
3759- // `FunctionReference` base class is required, because that's implementing `KFunction`.
3760- val baseClass = pluginContext.referenceClass(FqName (" kotlin.jvm.internal.FunctionReference" ))?.owner?.typeWith()
3761- ? : pluginContext.irBuiltIns.anyType
3762-
3763- val classId = extractGeneratedClass(ids, listOf (baseClass, fnInterfaceType), locId, currentDeclaration)
3764-
3765- helper.extractReceiverField()
3766-
3767- val isBigArity = type.arguments.size > BuiltInFunctionArity .BIG_ARITY
3768- val funLabels = if (isBigArity) {
3769- addFunctionNInvoke(ids.function, parameterTypes.last(), classId, locId)
3770- } else {
3771- addFunctionInvoke(ids.function, parameterTypes.dropLast(1 ), parameterTypes.last(), classId, locId)
3772- }
3773-
3774- helper.extractCallToReflectionTarget(
3775- funLabels,
3776- target,
3777- parameterTypes.last(),
3778- expressionTypeArguments,
3779- classTypeArguments,
3780- dispatchReceiverIdx,
3781- isBigArity,
3782- parameterTypes.dropLast(1 ))
3783-
37843770 // Add constructor (member ref) call:
37853771 val exprParent = parent.expr(functionReferenceExpr, callable)
37863772 val idMemberRef = tw.getFreshIdLabel<DbMemberref >()
@@ -3791,40 +3777,87 @@ open class KotlinFileExtractor(
37913777 tw.writeStatementEnclosingExpr(idMemberRef, exprParent.enclosingStmt)
37923778 tw.writeCallableBinding(idMemberRef, ids.constructor )
37933779
3794- val typeAccessArguments = if (isBigArity) listOf (parameterTypes.last()) else parameterTypes
3795- if (target is IrConstructorSymbol ) {
3796- val returnType = typeAccessArguments.last()
3780+ val targetCallableId = useFunction<DbCallable >(target.owner.realOverrideTarget, classTypeArguments)
3781+ tw.writeMemberRefBinding(idMemberRef, targetCallableId)
37973782
3798- val typeAccessId = extractTypeAccess(useType(fnInterfaceType, TypeContext .OTHER ), locId, idMemberRef, - 3 , callable, exprParent.enclosingStmt)
3799- typeAccessArguments.dropLast(1 ).forEachIndexed { argIdx, arg ->
3800- extractTypeAccessRecursive(arg, locId, typeAccessId, argIdx, callable, exprParent.enclosingStmt, TypeContext .GENERIC_ARGUMENT )
3801- }
3783+ val helper = CallableReferenceHelper (functionReferenceExpr, locId, ids)
38023784
3803- extractConstructorTypeAccess(returnType, useType(returnType), target, locId, typeAccessId, typeAccessArguments.count() - 1 , callable, exprParent.enclosingStmt)
3785+ val fnInterfaceType = getFunctionalInterfaceTypeWithTypeArgs(type.arguments)
3786+ if (fnInterfaceType == null ) {
3787+ logger.warnElement(" Cannot find functional interface type for function reference" , functionReferenceExpr)
38043788 } else {
3805- extractTypeAccessRecursive(fnInterfaceType, locId, idMemberRef, - 3 , callable, exprParent.enclosingStmt)
3806- }
3789+ val currentDeclaration = declarationStack.peek()
3790+ // `FunctionReference` base class is required, because that's implementing `KFunction`.
3791+ val baseClass = pluginContext.referenceClass(FqName (" kotlin.jvm.internal.FunctionReference" ))?.owner?.typeWith()
3792+ ? : pluginContext.irBuiltIns.anyType
38073793
3808- tw.writeMemberRefBinding(idMemberRef, targetCallableId)
3794+ val classId = extractGeneratedClass(ids, listOf (baseClass, fnInterfaceType), locId, currentDeclaration)
3795+
3796+ helper.extractReceiverField()
3797+
3798+ val isBigArity = type.arguments.size > BuiltInFunctionArity .BIG_ARITY
3799+ val funLabels = if (isBigArity) {
3800+ addFunctionNInvoke(ids.function, parameterTypes.last(), classId, locId)
3801+ } else {
3802+ addFunctionInvoke(ids.function, parameterTypes.dropLast(1 ), parameterTypes.last(), classId, locId)
3803+ }
3804+
3805+ helper.extractCallToReflectionTarget(
3806+ funLabels,
3807+ target,
3808+ parameterTypes.last(),
3809+ expressionTypeArguments,
3810+ classTypeArguments,
3811+ dispatchReceiverIdx,
3812+ isBigArity,
3813+ parameterTypes.dropLast(1 ))
3814+
3815+ val typeAccessArguments = if (isBigArity) listOf (parameterTypes.last()) else parameterTypes
3816+ if (target is IrConstructorSymbol ) {
3817+ val returnType = typeAccessArguments.last()
3818+
3819+ val typeAccessId = extractTypeAccess(useType(fnInterfaceType, TypeContext .OTHER ), locId, idMemberRef, - 3 , callable, exprParent.enclosingStmt)
3820+ typeAccessArguments.dropLast(1 ).forEachIndexed { argIdx, arg ->
3821+ extractTypeAccessRecursive(arg, locId, typeAccessId, argIdx, callable, exprParent.enclosingStmt, TypeContext .GENERIC_ARGUMENT )
3822+ }
3823+
3824+ extractConstructorTypeAccess(returnType, useType(returnType), target, locId, typeAccessId, typeAccessArguments.count() - 1 , callable, exprParent.enclosingStmt)
3825+ } else {
3826+ extractTypeAccessRecursive(fnInterfaceType, locId, idMemberRef, - 3 , callable, exprParent.enclosingStmt)
3827+ }
38093828
3810- helper.extractConstructorArguments(callable, idMemberRef, exprParent.enclosingStmt)
3829+ helper.extractConstructorArguments(callable, idMemberRef, exprParent.enclosingStmt)
38113830
3812- tw.writeIsAnonymClass(classId, idMemberRef)
3831+ tw.writeIsAnonymClass(classId, idMemberRef)
3832+ }
38133833 }
38143834 }
38153835
3816- private fun getFunctionalInterfaceType (functionNTypeArguments : List <IrType >) =
3836+ private fun getFunctionalInterfaceType (functionNTypeArguments : List <IrType >): IrSimpleType ? {
38173837 if (functionNTypeArguments.size > BuiltInFunctionArity .BIG_ARITY ) {
3818- pluginContext.referenceClass(FqName (" kotlin.jvm.functions.FunctionN" ))!!
3819- .typeWith(functionNTypeArguments.last())
3838+ val funName = " kotlin.jvm.functions.FunctionN"
3839+ val theFun = pluginContext.referenceClass(FqName (funName))
3840+ if (theFun == null ) {
3841+ logger.warn(" Cannot find $funName for getFunctionalInterfaceType" )
3842+ return null
3843+ } else {
3844+ return theFun.typeWith(functionNTypeArguments.last())
3845+ }
38203846 } else {
3821- functionN(pluginContext)(functionNTypeArguments.size - 1 ).typeWith(functionNTypeArguments)
3847+ return functionN(pluginContext)(functionNTypeArguments.size - 1 ).typeWith(functionNTypeArguments)
38223848 }
3849+ }
38233850
3824- private fun getFunctionalInterfaceTypeWithTypeArgs (functionNTypeArguments : List <IrTypeArgument >) =
3851+ private fun getFunctionalInterfaceTypeWithTypeArgs (functionNTypeArguments : List <IrTypeArgument >): IrSimpleType ? =
38253852 if (functionNTypeArguments.size > BuiltInFunctionArity .BIG_ARITY ) {
3826- pluginContext.referenceClass(FqName (" kotlin.jvm.functions.FunctionN" ))!!
3827- .typeWithArguments(listOf (functionNTypeArguments.last()))
3853+ val funName = " kotlin.jvm.functions.FunctionN"
3854+ val theFun = pluginContext.referenceClass(FqName (funName))
3855+ if (theFun == null ) {
3856+ logger.warn(" Cannot find $funName for getFunctionalInterfaceTypeWithTypeArgs" )
3857+ null
3858+ } else {
3859+ theFun.typeWithArguments(listOf (functionNTypeArguments.last()))
3860+ }
38283861 } else {
38293862 functionN(pluginContext)(functionNTypeArguments.size - 1 ).symbol.typeWithArguments(functionNTypeArguments)
38303863 }
@@ -4327,6 +4360,10 @@ open class KotlinFileExtractor(
43274360
43284361 // Either Function1, ... Function22 or FunctionN type, but not Function23 or above.
43294362 val functionType = getFunctionalInterfaceTypeWithTypeArgs(st.arguments)
4363+ if (functionType == null ) {
4364+ logger.errorElement(" Cannot find functional interface." , e)
4365+ return
4366+ }
43304367
43314368 val invokeMethod = functionType.classOrNull?.owner?.declarations?.filterIsInstance<IrFunction >()?.find { it.name.asString() == OperatorNameConventions .INVOKE .asString()}
43324369 if (invokeMethod == null ) {
0 commit comments