Skip to content

Commit 51ada5c

Browse files
authored
Merge pull request #10130 from igfoo/igfoo/non-null-exprs
Kotlin: Fix some more not-null-exprs in the extractor
2 parents 085c12a + d5b414f commit 51ada5c

File tree

1 file changed

+102
-65
lines changed

1 file changed

+102
-65
lines changed

java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt

Lines changed: 102 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)