Skip to content

Commit 1ea8702

Browse files
committed
Kotlin: use $default functions to implement @jvmoverloads
This avoids extracting the default value expression in more than one place, which causes inconsistencies for e.g. anonymous classes, which expect to have a single `new` expression associated.
1 parent 12ab956 commit 1ea8702

File tree

3 files changed

+197
-191
lines changed

3 files changed

+197
-191
lines changed

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

Lines changed: 15 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.declarations.*
2121
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunction
2222
import org.jetbrains.kotlin.ir.expressions.*
2323
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
24+
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
2425
import org.jetbrains.kotlin.ir.symbols.*
2526
import org.jetbrains.kotlin.ir.types.*
2627
import org.jetbrains.kotlin.ir.util.*
@@ -1051,8 +1052,8 @@ open class KotlinFileExtractor(
10511052
if (!f.hasAnnotation(jvmOverloadsFqName))
10521053
return
10531054

1054-
fun extractGeneratedOverload(paramList: List<IrElement>) {
1055-
val overloadParameters = paramList.filterIsInstance<IrValueParameter>()
1055+
fun extractGeneratedOverload(paramList: List<IrValueParameter?>) {
1056+
val overloadParameters = paramList.filterNotNull()
10561057
// Note `overloadParameters` have incorrect parents and indices, since there is no actual IrFunction describing the required synthetic overload.
10571058
// We have to use the `overriddenAttributes` element of `DeclarationStackAdjuster` to fix up references to these parameters while we're extracting
10581059
// these synthetic overloads.
@@ -1072,67 +1073,33 @@ open class KotlinFileExtractor(
10721073

10731074
DeclarationStackAdjuster(f, overriddenAttributes).use {
10741075

1075-
fun extractNormalArgs(argParentId: Label<out DbExprparent>, idxOffset: Int, enclosingStmtId: Label<out DbStmt>) {
1076-
paramList.forEachIndexed { idx, param ->
1077-
when(param) {
1078-
is IrValueParameter -> {
1079-
// Forward a parameter:
1080-
val syntheticParamId = useValueParameter(param, overloadId)
1081-
extractVariableAccess(syntheticParamId, param.type, realFunctionLocId, argParentId, idxOffset + idx, overloadId, enclosingStmtId)
1082-
}
1083-
is IrExpression -> {
1084-
// Supply a default argument:
1085-
extractExpressionExpr(param, overloadId, argParentId, idxOffset + idx, enclosingStmtId)
1086-
}
1087-
else -> {
1088-
logger.errorElement("Unexpected parameter list entry", param)
1089-
}
1090-
}
1091-
}
1092-
}
1076+
// Create a synthetic function body that calls the corresponding $default function:
1077+
val regularArgs = paramList.map { it?.let { p -> IrGetValueImpl(-1, -1, p.symbol) } }
10931078

1094-
// Create a synthetic function body that calls the real function supplying default arguments where required:
10951079
if (f is IrConstructor) {
10961080
val blockId = extractBlockBody(overloadId, realFunctionLocId)
10971081
val constructorCallId = tw.getFreshIdLabel<DbConstructorinvocationstmt>()
10981082
tw.writeStmts_constructorinvocationstmt(constructorCallId, blockId, 0, overloadId)
10991083
tw.writeHasLocation(constructorCallId, realFunctionLocId)
1100-
tw.writeCallableBinding(constructorCallId, useFunction(f))
1084+
tw.writeCallableBinding(constructorCallId, getDefaultsMethodLabel(f))
11011085

1102-
extractNormalArgs(constructorCallId, 0, constructorCallId)
1086+
extractDefaultsCallArguments(constructorCallId, f, overloadId, constructorCallId, regularArgs, null, null)
11031087
} else {
1088+
val dispatchReceiver = f.dispatchReceiverParameter?.let { IrGetValueImpl(-1, -1, it.symbol) }
1089+
val extensionReceiver = f.extensionReceiverParameter?.let { IrGetValueImpl(-1, -1, it.symbol) }
1090+
11041091
extractExpressionBody(overloadId, realFunctionLocId).also { returnId ->
1105-
extractRawMethodAccess(
1106-
f,
1107-
realFunctionLocId,
1108-
f.returnType,
1109-
overloadId,
1110-
returnId,
1111-
0,
1112-
returnId,
1113-
f.valueParameters.size,
1114-
{ argParentId, idxOffset ->
1115-
extractNormalArgs(argParentId, idxOffset, returnId)
1116-
},
1117-
f.dispatchReceiverParameter?.type,
1118-
f.dispatchReceiverParameter?.let { { callId ->
1119-
extractThisAccess(it.type, overloadId, callId, -1, returnId, realFunctionLocId)
1120-
} },
1121-
f.extensionReceiverParameter?.let { { argParentId ->
1122-
val syntheticParamId = useValueParameter(it, overloadId)
1123-
extractVariableAccess(syntheticParamId, it.type, realFunctionLocId, argParentId, 0, overloadId, returnId)
1124-
} }
1125-
)
1092+
extractsDefaultsCall(f, realFunctionLocId, f.returnType, overloadId, returnId, 0, returnId, regularArgs, dispatchReceiver, extensionReceiver)
11261093
}
11271094
}
11281095
}
11291096
}
11301097
}
11311098

1132-
val paramList: MutableList<IrElement> = f.valueParameters.toMutableList()
1133-
for (n in (paramList.size - 1) downTo 0) {
1134-
(paramList[n] as? IrValueParameter)?.defaultValue?.expression?.let {
1135-
paramList[n] = it // Replace the last parameter that has a default with that default value.
1099+
val paramList: MutableList<IrValueParameter?> = f.valueParameters.toMutableList()
1100+
for (n in (f.valueParameters.size - 1) downTo 0) {
1101+
if (f.valueParameters[n].defaultValue != null) {
1102+
paramList[n] = null // Remove this parameter, to be replaced by a default value
11361103
extractGeneratedOverload(paramList)
11371104
}
11381105
}

0 commit comments

Comments
 (0)