Skip to content

Commit f377d25

Browse files
authored
Merge pull request #13919 from igfoo/igfoo/useFunction
Kotlin: useFunction might return null
2 parents 4e954c2 + 0eb6d1c commit f377d25

File tree

2 files changed

+137
-62
lines changed

2 files changed

+137
-62
lines changed

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

Lines changed: 120 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -552,9 +552,13 @@ open class KotlinFileExtractor(
552552
logger.warnElement("Expected annotation property to define a getter", prop)
553553
} else {
554554
val getterId = useFunction<DbMethod>(getter)
555-
val exprId = extractAnnotationValueExpression(v, id, i, "{$getterId}", getter.returnType, extractEnumTypeAccesses)
556-
if (exprId != null) {
557-
tw.writeAnnotValue(id, getterId, exprId)
555+
if (getterId == null) {
556+
logger.errorElement("Couldn't get ID for getter", getter)
557+
} else {
558+
val exprId = extractAnnotationValueExpression(v, id, i, "{$getterId}", getter.returnType, extractEnumTypeAccesses)
559+
if (exprId != null) {
560+
tw.writeAnnotValue(id, getterId, exprId)
561+
}
558562
}
559563
}
560564
}
@@ -979,6 +983,10 @@ open class KotlinFileExtractor(
979983
private fun extractInstanceInitializerBlock(parent: StmtParent, enclosingConstructor: IrConstructor) {
980984
with("object initializer block", enclosingConstructor) {
981985
val constructorId = useFunction<DbConstructor>(enclosingConstructor)
986+
if (constructorId == null) {
987+
logger.errorElement("Cannot get ID for constructor", enclosingConstructor)
988+
return
989+
}
982990
val enclosingClass = enclosingConstructor.parentClassOrNull
983991
if (enclosingClass == null) {
984992
logger.errorElement("Constructor's parent is not a class", enclosingConstructor)
@@ -1410,10 +1418,17 @@ open class KotlinFileExtractor(
14101418

14111419
val sourceDeclaration =
14121420
overriddenAttributes?.sourceDeclarationId ?:
1413-
if (typeSubstitution != null && overriddenAttributes?.id == null)
1414-
useFunction(f)
1415-
else
1421+
if (typeSubstitution != null && overriddenAttributes?.id == null) {
1422+
val sourceFunId = useFunction<DbCallable>(f)
1423+
if (sourceFunId == null) {
1424+
logger.errorElement("Cannot get source ID for function", f)
1425+
id // TODO: This is wrong; we ought to just fail in this case
1426+
} else {
1427+
sourceFunId
1428+
}
1429+
} else {
14161430
id
1431+
}
14171432

14181433
val extReceiver = f.extensionReceiverParameter
14191434
// The following parameter order is correct, because member $default methods (where the order would be [dispatchParam], [extensionParam], normalParams) are not extracted here
@@ -2926,7 +2941,11 @@ open class KotlinFileExtractor(
29262941
tw.writeStmts_throwstmt(throwId, stmtParent.parent, stmtParent.idx, callable)
29272942
tw.writeHasLocation(throwId, locId)
29282943
val newExprId = extractNewExpr(it, null, thrownType, locId, throwId, 0, callable, throwId)
2929-
extractTypeAccess(thrownType, locId, newExprId, -3, callable, throwId)
2944+
if (newExprId == null) {
2945+
logger.errorElement("No ID for newExpr in noWhenBranchMatchedException", c)
2946+
} else {
2947+
extractTypeAccess(thrownType, locId, newExprId, -3, callable, throwId)
2948+
}
29302949
}
29312950
}
29322951
isBuiltinCallInternal(c, "illegalArgumentException") -> {
@@ -3270,7 +3289,14 @@ open class KotlinFileExtractor(
32703289
idx: Int,
32713290
callable: Label<out DbCallable>,
32723291
enclosingStmt: Label<out DbStmt>
3273-
): Label<DbNewexpr> = extractNewExpr(useFunction<DbConstructor>(calledConstructor, constructorTypeArgs), constructedType, locId, parent, idx, callable, enclosingStmt)
3292+
): Label<DbNewexpr>? {
3293+
val funId = useFunction<DbConstructor>(calledConstructor, constructorTypeArgs)
3294+
if (funId == null) {
3295+
logger.error("Cannot get ID for newExpr function")
3296+
return null
3297+
}
3298+
return extractNewExpr(funId, constructedType, locId, parent, idx, callable, enclosingStmt)
3299+
}
32743300

32753301
private fun needsObinitFunction(c: IrClass) = c.primaryConstructor == null && c.constructors.count() > 1
32763302

@@ -3310,26 +3336,31 @@ open class KotlinFileExtractor(
33103336
extractDefaultsCallArguments(it, e.symbol.owner, callable, enclosingStmt, valueArgs, null, null)
33113337
}
33123338
} else {
3313-
extractNewExpr(e.symbol.owner, eType.arguments, type, locId, parent, idx, callable, enclosingStmt).also {
3314-
3315-
val realCallTarget = e.symbol.owner.realOverrideTarget
3316-
// Generated constructor calls to kotlin.Enum have no arguments in IR, but the constructor takes two parameters.
3317-
if (e is IrEnumConstructorCall &&
3318-
realCallTarget is IrConstructor &&
3319-
realCallTarget.parentClassOrNull?.fqNameWhenAvailable?.asString() == "kotlin.Enum" &&
3320-
realCallTarget.valueParameters.size == 2 &&
3321-
realCallTarget.valueParameters[0].type == pluginContext.irBuiltIns.stringType &&
3322-
realCallTarget.valueParameters[1].type == pluginContext.irBuiltIns.intType) {
3323-
3324-
val id0 = extractNull(pluginContext.irBuiltIns.stringType, locId, it, 0, callable, enclosingStmt)
3325-
tw.writeCompiler_generated(id0, CompilerGeneratedKinds.ENUM_CONSTRUCTOR_ARGUMENT.kind)
3326-
3327-
val id1 = extractConstantInteger(0, locId, it, 1, callable, enclosingStmt)
3328-
tw.writeCompiler_generated(id1, CompilerGeneratedKinds.ENUM_CONSTRUCTOR_ARGUMENT.kind)
3329-
} else {
3330-
extractCallValueArguments(it, e, enclosingStmt, callable, 0)
3331-
}
3339+
val newExprId = extractNewExpr(e.symbol.owner, eType.arguments, type, locId, parent, idx, callable, enclosingStmt)
3340+
if (newExprId == null) {
3341+
logger.errorElement("Cannot get newExpr ID", e)
3342+
return
3343+
}
3344+
3345+
val realCallTarget = e.symbol.owner.realOverrideTarget
3346+
// Generated constructor calls to kotlin.Enum have no arguments in IR, but the constructor takes two parameters.
3347+
if (e is IrEnumConstructorCall &&
3348+
realCallTarget is IrConstructor &&
3349+
realCallTarget.parentClassOrNull?.fqNameWhenAvailable?.asString() == "kotlin.Enum" &&
3350+
realCallTarget.valueParameters.size == 2 &&
3351+
realCallTarget.valueParameters[0].type == pluginContext.irBuiltIns.stringType &&
3352+
realCallTarget.valueParameters[1].type == pluginContext.irBuiltIns.intType) {
3353+
3354+
val id0 = extractNull(pluginContext.irBuiltIns.stringType, locId, newExprId, 0, callable, enclosingStmt)
3355+
tw.writeCompiler_generated(id0, CompilerGeneratedKinds.ENUM_CONSTRUCTOR_ARGUMENT.kind)
3356+
3357+
val id1 = extractConstantInteger(0, locId, newExprId, 1, callable, enclosingStmt)
3358+
tw.writeCompiler_generated(id1, CompilerGeneratedKinds.ENUM_CONSTRUCTOR_ARGUMENT.kind)
3359+
} else {
3360+
extractCallValueArguments(newExprId, e, enclosingStmt, callable, 0)
33323361
}
3362+
3363+
newExprId
33333364
}
33343365

33353366
if (isAnonymous) {
@@ -3698,9 +3729,13 @@ open class KotlinFileExtractor(
36983729

36993730
val locId = tw.getLocation(e)
37003731
val methodId = useFunction<DbConstructor>(e.symbol.owner)
3732+
if (methodId == null) {
3733+
logger.errorElement("Cannot get ID for delegating constructor", e)
3734+
} else {
3735+
tw.writeCallableBinding(id.cast<DbCaller>(), methodId)
3736+
}
37013737

37023738
tw.writeHasLocation(id, locId)
3703-
tw.writeCallableBinding(id.cast<DbCaller>(), methodId)
37043739
extractCallValueArguments(id, e, id, callable, 0)
37053740
val dr = e.dispatchReceiver
37063741
if (dr != null) {
@@ -4636,7 +4671,11 @@ open class KotlinFileExtractor(
46364671
extractExprContext(callId, locId, labels.methodId, retId)
46374672

46384673
val callableId = useFunction<DbCallable>(target.owner.realOverrideTarget, classTypeArgsIncludingOuterClasses)
4639-
tw.writeCallableBinding(callId.cast<DbCaller>(), callableId)
4674+
if (callableId == null) {
4675+
logger.error("Cannot get ID for reflection target")
4676+
} else {
4677+
tw.writeCallableBinding(callId.cast<DbCaller>(), callableId)
4678+
}
46404679

46414680
val useFirstArgAsDispatch: Boolean
46424681
if (dispatchReceiverInfo != null) {
@@ -4818,20 +4857,24 @@ open class KotlinFileExtractor(
48184857
val getterReturnType = parameterTypes.last()
48194858

48204859
if (getter != null) {
4821-
val getLabels = addFunctionManual(tw.getFreshIdLabel(), OperatorNameConventions.GET.asString(), getterParameterTypes, getterReturnType, classId, locId)
48224860
val getterCallableId = useFunction<DbCallable>(getter.owner.realOverrideTarget, classTypeArguments)
4861+
if (getterCallableId == null) {
4862+
logger.errorElement("Cannot get ID for getter", propertyReferenceExpr)
4863+
} else {
4864+
val getLabels = addFunctionManual(tw.getFreshIdLabel(), OperatorNameConventions.GET.asString(), getterParameterTypes, getterReturnType, classId, locId)
4865+
4866+
helper.extractCallToReflectionTarget(
4867+
getLabels,
4868+
getter,
4869+
getterReturnType,
4870+
expressionTypeArguments,
4871+
classTypeArguments
4872+
)
48234873

4824-
helper.extractCallToReflectionTarget(
4825-
getLabels,
4826-
getter,
4827-
getterReturnType,
4828-
expressionTypeArguments,
4829-
classTypeArguments
4830-
)
4831-
4832-
tw.writePropertyRefGetBinding(idPropertyRef, getterCallableId)
4874+
tw.writePropertyRefGetBinding(idPropertyRef, getterCallableId)
48334875

4834-
helper.extractPropertyReferenceInvoke(getLabels.methodId, getterParameterTypes, getterReturnType)
4876+
helper.extractPropertyReferenceInvoke(getLabels.methodId, getterParameterTypes, getterReturnType)
4877+
}
48354878
} else {
48364879
// Property without a getter.
48374880
if (backingField == null) {
@@ -4852,19 +4895,22 @@ open class KotlinFileExtractor(
48524895
}
48534896

48544897
if (setter != null) {
4855-
val setLabels = addFunctionManual(tw.getFreshIdLabel(), OperatorNameConventions.SET.asString(), parameterTypes, pluginContext.irBuiltIns.unitType, classId, locId)
4856-
48574898
val setterCallableId = useFunction<DbCallable>(setter.owner.realOverrideTarget, classTypeArguments)
4899+
if (setterCallableId == null) {
4900+
logger.errorElement("Cannot get ID for setter", propertyReferenceExpr)
4901+
} else {
4902+
val setLabels = addFunctionManual(tw.getFreshIdLabel(), OperatorNameConventions.SET.asString(), parameterTypes, pluginContext.irBuiltIns.unitType, classId, locId)
48584903

4859-
helper.extractCallToReflectionTarget(
4860-
setLabels,
4861-
setter,
4862-
pluginContext.irBuiltIns.unitType,
4863-
expressionTypeArguments,
4864-
classTypeArguments
4865-
)
4904+
helper.extractCallToReflectionTarget(
4905+
setLabels,
4906+
setter,
4907+
pluginContext.irBuiltIns.unitType,
4908+
expressionTypeArguments,
4909+
classTypeArguments
4910+
)
48664911

4867-
tw.writePropertyRefSetBinding(idPropertyRef, setterCallableId)
4912+
tw.writePropertyRefSetBinding(idPropertyRef, setterCallableId)
4913+
}
48684914
} else {
48694915
if (backingField != null && !backingField.owner.isFinal) {
48704916
val setLabels = addFunctionManual(tw.getFreshIdLabel(), OperatorNameConventions.SET.asString(), parameterTypes, pluginContext.irBuiltIns.unitType, classId, locId)
@@ -4999,7 +5045,11 @@ open class KotlinFileExtractor(
49995045
tw.writeCallableBinding(idMemberRef, ids.constructor)
50005046

50015047
val targetCallableId = useFunction<DbCallable>(target.owner.realOverrideTarget, classTypeArguments)
5002-
tw.writeMemberRefBinding(idMemberRef, targetCallableId)
5048+
if (targetCallableId == null) {
5049+
logger.errorElement("Cannot get ID for function reference callable", functionReferenceExpr)
5050+
} else {
5051+
tw.writeMemberRefBinding(idMemberRef, targetCallableId)
5052+
}
50035053

50045054
val helper = CallableReferenceHelper(functionReferenceExpr, locId, ids)
50055055

@@ -5145,7 +5195,11 @@ open class KotlinFileExtractor(
51455195
tw.writeExprsKotlinType(callId, callType.kotlinResult.id)
51465196
extractExprContext(callId, locId, funLabels.methodId, retId)
51475197
val calledMethodId = useFunction<DbMethod>(lambda)
5148-
tw.writeCallableBinding(callId, calledMethodId)
5198+
if (calledMethodId == null) {
5199+
logger.errorElement("Cannot get ID for called lambda", lambda)
5200+
} else {
5201+
tw.writeCallableBinding(callId, calledMethodId)
5202+
}
51495203

51505204
// this access
51515205
extractThisAccess(ids.type, funLabels.methodId, callId, -1, retId, locId)
@@ -5614,7 +5668,11 @@ open class KotlinFileExtractor(
56145668
tw.writeExprsKotlinType(callId, callType.kotlinResult.id)
56155669
extractExprContext(callId, locId, ids.function, returnId)
56165670
val calledMethodId = useFunction<DbMethod>(invokeMethod, functionType.arguments)
5617-
tw.writeCallableBinding(callId, calledMethodId)
5671+
if (calledMethodId == null) {
5672+
logger.errorElement("Cannot get ID for called method", invokeMethod)
5673+
} else {
5674+
tw.writeCallableBinding(callId, calledMethodId)
5675+
}
56185676

56195677
// <fn> access
56205678
val lhsId = tw.getFreshIdLabel<DbVaraccess>()
@@ -5737,14 +5795,17 @@ open class KotlinFileExtractor(
57375795
if (baseConstructor == null) {
57385796
logger.warnElement("Cannot find base constructor", elementToReportOn)
57395797
} else {
5740-
val superCallId = tw.getFreshIdLabel<DbSuperconstructorinvocationstmt>()
5741-
tw.writeStmts_superconstructorinvocationstmt(superCallId, constructorBlockId, 0, ids.constructor)
5742-
57435798
val baseConstructorId = useFunction<DbConstructor>(baseConstructor)
5799+
if (baseConstructorId == null) {
5800+
logger.errorElement("Cannot find base constructor ID", elementToReportOn)
5801+
} else {
5802+
val superCallId = tw.getFreshIdLabel<DbSuperconstructorinvocationstmt>()
5803+
tw.writeStmts_superconstructorinvocationstmt(superCallId, constructorBlockId, 0, ids.constructor)
57445804

5745-
tw.writeHasLocation(superCallId, locId)
5746-
tw.writeCallableBinding(superCallId.cast<DbCaller>(), baseConstructorId)
5747-
extractSuperconstructorArgs(superCallId)
5805+
tw.writeHasLocation(superCallId, locId)
5806+
tw.writeCallableBinding(superCallId.cast<DbCaller>(), baseConstructorId)
5807+
extractSuperconstructorArgs(superCallId)
5808+
}
57485809
}
57495810
}
57505811

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,16 +1322,30 @@ open class KotlinUsesExtractor(
13221322
else -> false
13231323
}
13241324

1325-
fun <T: DbCallable> useFunction(f: IrFunction, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>? = null, noReplace: Boolean = false): Label<out T> {
1326-
return useFunction(f, null, classTypeArgsIncludingOuterClasses, noReplace)
1325+
fun <T: DbCallable> useFunction(f: IrFunction, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>? = null, noReplace: Boolean = false): Label<out T>? {
1326+
if (f.isLocalFunction()) {
1327+
val ids = getLocallyVisibleFunctionLabels(f)
1328+
return ids.function.cast<T>()
1329+
}
1330+
val javaFun = kotlinFunctionToJavaEquivalent(f, noReplace)
1331+
val parentId = useDeclarationParent(javaFun.parent, false, classTypeArgsIncludingOuterClasses, true)
1332+
if (parentId == null) {
1333+
logger.error("Couldn't find parent ID for function ${f.name.asString()}")
1334+
return null
1335+
}
1336+
return useFunction(f, javaFun, parentId, classTypeArgsIncludingOuterClasses)
13271337
}
13281338

1329-
fun <T: DbCallable> useFunction(f: IrFunction, parentId: Label<out DbElement>?, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, noReplace: Boolean = false): Label<out T> {
1339+
fun <T: DbCallable> useFunction(f: IrFunction, parentId: Label<out DbElement>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, noReplace: Boolean = false): Label<out T> {
13301340
if (f.isLocalFunction()) {
13311341
val ids = getLocallyVisibleFunctionLabels(f)
13321342
return ids.function.cast<T>()
13331343
}
13341344
val javaFun = kotlinFunctionToJavaEquivalent(f, noReplace)
1345+
return useFunction(f, javaFun, parentId, classTypeArgsIncludingOuterClasses)
1346+
}
1347+
1348+
private fun <T: DbCallable> useFunction(f: IrFunction, javaFun: IrFunction, parentId: Label<out DbElement>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?): Label<out T> {
13351349
val label = getFunctionLabel(javaFun, parentId, classTypeArgsIncludingOuterClasses)
13361350
val id: Label<T> = tw.getLabelFor(label) {
13371351
extractPrivateSpecialisedDeclaration(f, classTypeArgsIncludingOuterClasses)

0 commit comments

Comments
 (0)