[IR] Implement bridges generation for MFVC
#KT-1179
This commit is contained in:
committed by
teamcity
parent
2896f5613d
commit
ee2d327243
+60
-12
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.utils.SmartList
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||||
|
import kotlin.collections.set
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate bridge methods to fix virtual dispatch after type erasure and to adapt Kotlin collections to
|
* Generate bridge methods to fix virtual dispatch after type erasure and to adapt Kotlin collections to
|
||||||
@@ -341,12 +342,14 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass
|
|||||||
for (override in irFunction.allOverridden()) {
|
for (override in irFunction.allOverridden()) {
|
||||||
if (override.isFakeOverride) continue
|
if (override.isFakeOverride) continue
|
||||||
|
|
||||||
val signature = override.jvmMethod
|
val target = override.mangleFunctionIfNeeded()
|
||||||
|
|
||||||
|
val signature = target.jvmMethod
|
||||||
if (targetMethod != signature && signature !in blacklist) {
|
if (targetMethod != signature && signature !in blacklist) {
|
||||||
val bridge = generated.getOrPut(signature) {
|
val bridge = generated.getOrPut(signature) {
|
||||||
Bridge(override, signature)
|
Bridge(target, signature)
|
||||||
}
|
}
|
||||||
bridge.overriddenSymbols += override.symbol
|
bridge.overriddenSymbols += target.symbol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,6 +361,18 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass
|
|||||||
.forEach { irClass.addBridge(it, bridgeTarget) }
|
.forEach { irClass.addBridge(it, bridgeTarget) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun IrSimpleFunction.mangleFunctionIfNeeded(): IrSimpleFunction {
|
||||||
|
if (!hasMangledReturnType && !hasMangledParameters()) return this
|
||||||
|
val replacement = context.multiFieldValueClassReplacements.getReplacementFunction(this)
|
||||||
|
?: context.inlineClassReplacements.getReplacementFunction(this)
|
||||||
|
?: return this
|
||||||
|
if (name.asString().substringAfterLast('-') == replacement.name.asString().substringAfterLast('-')) {
|
||||||
|
// function is already mangled
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
return replacement
|
||||||
|
}
|
||||||
|
|
||||||
private fun IrSimpleFunction.isClashingWithPotentialBridge(name: Name, signature: Method): Boolean =
|
private fun IrSimpleFunction.isClashingWithPotentialBridge(name: Name, signature: Method): Boolean =
|
||||||
(!this.isFakeOverride || this.modality == Modality.FINAL) && this.name == name && this.jvmMethod == signature
|
(!this.isFakeOverride || this.modality == Modality.FINAL) && this.name == name && this.jvmMethod == signature
|
||||||
|
|
||||||
@@ -612,16 +627,49 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass
|
|||||||
) =
|
) =
|
||||||
irCastIfNeeded(
|
irCastIfNeeded(
|
||||||
irCall(target, origin = IrStatementOrigin.BRIDGE_DELEGATION, superQualifierSymbol = superQualifierSymbol).apply {
|
irCall(target, origin = IrStatementOrigin.BRIDGE_DELEGATION, superQualifierSymbol = superQualifierSymbol).apply {
|
||||||
for ((param, targetParam) in bridge.explicitParameters.zip(target.explicitParameters)) {
|
val mfvcOrOriginal =
|
||||||
putArgument(
|
this@BridgeLowering.context.inlineClassReplacements.originalFunctionForMethodReplacement[target] ?: target
|
||||||
targetParam,
|
val structure = with(this@BridgeLowering.context.multiFieldValueClassReplacements) {
|
||||||
irGet(param).let { argument ->
|
originalFunctionForMethodReplacement[mfvcOrOriginal]
|
||||||
if (param == bridge.dispatchReceiverParameter)
|
?.let { bindingParameterTemplateStructure[it] }
|
||||||
argument
|
?.also { structure ->
|
||||||
else
|
val errorMessage = { "Bad parameters structure: $structure" }
|
||||||
irCastIfNeeded(argument, targetParam.type.upperBound)
|
require(structure.size == bridge.explicitParametersCount) { errorMessage() }
|
||||||
|
require(structure.sumOf { it.valueParameters.size } == target.explicitParametersCount) { errorMessage() }
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
|
fun irGetOrCast(bridgeParameter: IrValueParameter, targetParameter: IrValueParameter) =
|
||||||
|
irGet(bridgeParameter).let { argument ->
|
||||||
|
if (bridgeParameter == bridge.dispatchReceiverParameter)
|
||||||
|
argument
|
||||||
|
else
|
||||||
|
irCastIfNeeded(argument, targetParameter.type.upperBound)
|
||||||
|
}
|
||||||
|
|
||||||
|
val targetParameters = target.explicitParameters
|
||||||
|
val flattenedBridgeArguments = when (structure) {
|
||||||
|
null -> bridge.explicitParameters.zip(target.explicitParameters, ::irGetOrCast)
|
||||||
|
else -> {
|
||||||
|
var index = 0
|
||||||
|
(structure zip bridge.explicitParameters).flatMap { (remappedParameter, bridgeParameter) ->
|
||||||
|
when (remappedParameter) {
|
||||||
|
is MultiFieldValueClassMapping -> remappedParameter.declarations.unboxMethods.map { unboxFunction ->
|
||||||
|
irCall(unboxFunction).apply {
|
||||||
|
dispatchReceiver =
|
||||||
|
irCastIfNeeded(irGet(bridgeParameter), remappedParameter.declarations.valueClass.defaultType)
|
||||||
|
}
|
||||||
|
}.also { index += it.size }
|
||||||
|
is RegularMapping -> listOf(irGetOrCast(bridgeParameter, targetParameters[index++]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require(targetParameters.size == flattenedBridgeArguments.size) {
|
||||||
|
"Incorrect number of arguments: ${flattenedBridgeArguments.size} instead of ${targetParameters.size}"
|
||||||
|
}
|
||||||
|
for ((targetParam, argument) in target.explicitParameters zip flattenedBridgeArguments) {
|
||||||
|
putArgument(targetParam, argument)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
bridge.returnType.upperBound
|
bridge.returnType.upperBound
|
||||||
|
|||||||
+1
-1
@@ -47,7 +47,7 @@ private class JvmDefaultConstructorLowering(val context: JvmBackendContext) : Cl
|
|||||||
if (DescriptorVisibilities.isPrivate(primaryConstructor.visibility))
|
if (DescriptorVisibilities.isPrivate(primaryConstructor.visibility))
|
||||||
return
|
return
|
||||||
|
|
||||||
if (primaryConstructor.hasMangledParameters)
|
if (primaryConstructor.hasMangledParameters())
|
||||||
return
|
return
|
||||||
|
|
||||||
if (primaryConstructor.valueParameters.isEmpty() || !primaryConstructor.valueParameters.all { it.hasDefaultValue() })
|
if (primaryConstructor.valueParameters.isEmpty() || !primaryConstructor.valueParameters.all { it.hasDefaultValue() })
|
||||||
|
|||||||
+1
-61
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.ir.IrStatement
|
|||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
|
import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
@@ -30,8 +29,6 @@ import org.jetbrains.kotlin.ir.types.isNullable
|
|||||||
import org.jetbrains.kotlin.ir.types.makeNotNull
|
import org.jetbrains.kotlin.ir.types.makeNotNull
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.resolve.JVM_INLINE_ANNOTATION_FQ_NAME
|
import org.jetbrains.kotlin.resolve.JVM_INLINE_ANNOTATION_FQ_NAME
|
||||||
|
|
||||||
val jvmInlineClassPhase = makeIrFilePhase(
|
val jvmInlineClassPhase = makeIrFilePhase(
|
||||||
@@ -117,64 +114,7 @@ private class JvmInlineClassLowering(context: JvmBackendContext) : JvmValueClass
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createBridgeFunction(
|
override fun createBridgeBody(source: IrSimpleFunction, target: IrSimpleFunction, original: IrFunction, inverted: Boolean) {
|
||||||
function: IrSimpleFunction,
|
|
||||||
replacement: IrSimpleFunction
|
|
||||||
): IrSimpleFunction {
|
|
||||||
val bridgeFunction = createBridgeDeclaration(
|
|
||||||
function,
|
|
||||||
when {
|
|
||||||
// If the original function has signature which need mangling we still need to replace it with a mangled version.
|
|
||||||
(!function.isFakeOverride || function.findInterfaceImplementation(context.state.jvmDefaultMode) != null) &&
|
|
||||||
function.signatureRequiresMangling() ->
|
|
||||||
replacement.name
|
|
||||||
// Since we remove the corresponding property symbol from the bridge we need to resolve getter/setter
|
|
||||||
// names at this point.
|
|
||||||
replacement.isGetter ->
|
|
||||||
Name.identifier(JvmAbi.getterName(replacement.correspondingPropertySymbol!!.owner.name.asString()))
|
|
||||||
replacement.isSetter ->
|
|
||||||
Name.identifier(JvmAbi.setterName(replacement.correspondingPropertySymbol!!.owner.name.asString()))
|
|
||||||
else ->
|
|
||||||
function.name
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Update the overridden symbols to point to their inline class replacements
|
|
||||||
bridgeFunction.overriddenSymbols = replacement.overriddenSymbols
|
|
||||||
|
|
||||||
// Replace the function body with a wrapper
|
|
||||||
if (bridgeFunction.isFakeOverride && bridgeFunction.parentAsClass.isSingleFieldValueClass) {
|
|
||||||
// Fake overrides redirect from the replacement to the original function, which is in turn replaced during interfacePhase.
|
|
||||||
createBridgeBody(replacement, bridgeFunction)
|
|
||||||
} else {
|
|
||||||
createBridgeBody(bridgeFunction, replacement)
|
|
||||||
}
|
|
||||||
return bridgeFunction
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrSimpleFunction.signatureRequiresMangling() =
|
|
||||||
fullValueParameterList.any { it.type.requiresMangling } ||
|
|
||||||
context.state.functionsWithInlineClassReturnTypesMangled && returnType.requiresMangling
|
|
||||||
|
|
||||||
// We may need to add a bridge method for inline class methods with static replacements. Ideally, we'd do this in BridgeLowering,
|
|
||||||
// but unfortunately this is a special case in the old backend. The bridge method is not marked as such and does not follow the normal
|
|
||||||
// visibility rules for bridge methods.
|
|
||||||
private fun createBridgeDeclaration(source: IrSimpleFunction, mangledName: Name) =
|
|
||||||
context.irFactory.buildFun {
|
|
||||||
updateFrom(source)
|
|
||||||
name = mangledName
|
|
||||||
returnType = source.returnType
|
|
||||||
}.apply {
|
|
||||||
copyParameterDeclarationsFrom(source)
|
|
||||||
annotations = source.annotations
|
|
||||||
parent = source.parent
|
|
||||||
// We need to ensure that this bridge has the same attribute owner as its static inline class replacement, since this
|
|
||||||
// is used in [CoroutineCodegen.isStaticInlineClassReplacementDelegatingCall] to identify the bridge and avoid generating
|
|
||||||
// a continuation class.
|
|
||||||
copyAttributes(source)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createBridgeBody(source: IrSimpleFunction, target: IrSimpleFunction) {
|
|
||||||
source.body = context.createIrBuilder(source.symbol, source.startOffset, source.endOffset).run {
|
source.body = context.createIrBuilder(source.symbol, source.startOffset, source.endOffset).run {
|
||||||
irExprBody(irCall(target).apply {
|
irExprBody(irCall(target).apply {
|
||||||
passTypeArgumentsFrom(source)
|
passTypeArgumentsFrom(source)
|
||||||
|
|||||||
+58
-17
@@ -9,7 +9,12 @@ import org.jetbrains.kotlin.backend.common.ir.createDispatchReceiverParameter
|
|||||||
import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
|
import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||||
|
import org.jetbrains.kotlin.backend.common.pop
|
||||||
|
import org.jetbrains.kotlin.backend.common.push
|
||||||
import org.jetbrains.kotlin.backend.jvm.*
|
import org.jetbrains.kotlin.backend.jvm.*
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.MultiFieldValueClassMapping
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.RegularMapping
|
||||||
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.ValueParameterTemplate
|
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.ValueParameterTemplate
|
||||||
import org.jetbrains.kotlin.backend.jvm.MultiFieldValueClassSpecificDeclarations.ImplementationAgnostic
|
import org.jetbrains.kotlin.backend.jvm.MultiFieldValueClassSpecificDeclarations.ImplementationAgnostic
|
||||||
import org.jetbrains.kotlin.backend.jvm.MultiFieldValueClassSpecificDeclarations.VirtualProperty
|
import org.jetbrains.kotlin.backend.jvm.MultiFieldValueClassSpecificDeclarations.VirtualProperty
|
||||||
@@ -55,8 +60,12 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
|
|||||||
symbol2setters[original] = listOf(if (replacement.isAssignable) { _, value -> irSet(replacement, value) } else null)
|
symbol2setters[original] = listOf(if (replacement.isAssignable) { _, value -> irSet(replacement, value) } else null)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun remapSymbol(original: IrValueSymbol, unboxed: List<VirtualProperty<Unit>>): Unit =
|
fun remapSymbol(
|
||||||
remapSymbol(original, replacements.getDeclarations(original.owner.type.erasedUpperBound)!!.ImplementationAgnostic(unboxed))
|
original: IrValueSymbol,
|
||||||
|
unboxed: List<VirtualProperty<Unit>>,
|
||||||
|
declarations: MultiFieldValueClassSpecificDeclarations
|
||||||
|
): Unit =
|
||||||
|
remapSymbol(original, declarations.ImplementationAgnostic(unboxed))
|
||||||
|
|
||||||
fun remapSymbol(original: IrValueSymbol, unboxed: ImplementationAgnostic<Unit>) {
|
fun remapSymbol(original: IrValueSymbol, unboxed: ImplementationAgnostic<Unit>) {
|
||||||
symbol2getter[original] = {
|
symbol2getter[original] = {
|
||||||
@@ -314,9 +323,39 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
|
|||||||
valueClass.declarations += properties.values.map { it.getter!!.apply { parent = valueClass } }
|
valueClass.declarations += properties.values.map { it.getter!!.apply { parent = valueClass } }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createBridgeFunction(function: IrSimpleFunction, replacement: IrSimpleFunction): IrSimpleFunction? {
|
override fun createBridgeBody(source: IrSimpleFunction, target: IrSimpleFunction, original: IrFunction, inverted: Boolean) {
|
||||||
return null // todo
|
|
||||||
// todo change return type to non-nullable for base class
|
allScopes.push(createScope(source))
|
||||||
|
source.body = context.createIrBuilder(source.symbol, source.startOffset, source.endOffset).run {
|
||||||
|
if (inverted) {
|
||||||
|
irExprBody(irCall(target).apply {
|
||||||
|
passTypeArgumentsFrom(source)
|
||||||
|
val structure: List<RemappedParameter> = replacements.bindingParameterTemplateStructure[original]!!
|
||||||
|
var flattenedIndex = 0
|
||||||
|
for ((remappedParameter, targetParameter) in structure zip target.explicitParameters) {
|
||||||
|
when (remappedParameter) {
|
||||||
|
is MultiFieldValueClassMapping -> putArgument(
|
||||||
|
targetParameter,
|
||||||
|
irCall(remappedParameter.declarations.boxMethod).apply {
|
||||||
|
source.explicitParameters
|
||||||
|
.slice(flattenedIndex until flattenedIndex + remappedParameter.valueParameters.size)
|
||||||
|
.forEachIndexed { index, boxParameter -> putValueArgument(index, irGet(boxParameter)) }
|
||||||
|
.also { flattenedIndex += remappedParameter.valueParameters.size }
|
||||||
|
})
|
||||||
|
is RegularMapping -> putArgument(targetParameter, irGet(source.explicitParameters[flattenedIndex++]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
irExprBody(irCall(original).apply { // not target as it will be replaced during lowering
|
||||||
|
passTypeArgumentsFrom(source)
|
||||||
|
for ((parameter, newParameter) in source.explicitParameters.zip(original.explicitParameters)) {
|
||||||
|
putArgument(newParameter, irGet(parameter))
|
||||||
|
}
|
||||||
|
}).transform(this@JvmMultiFieldValueClassLowering, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allScopes.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addBindingsFor(original: IrFunction, replacement: IrFunction) {
|
override fun addBindingsFor(original: IrFunction, replacement: IrFunction) {
|
||||||
@@ -324,19 +363,19 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
|
|||||||
require(parametersStructure.size == original.explicitParameters.size) {
|
require(parametersStructure.size == original.explicitParameters.size) {
|
||||||
"Wrong value parameters structure: $parametersStructure"
|
"Wrong value parameters structure: $parametersStructure"
|
||||||
}
|
}
|
||||||
require(parametersStructure.sumOf { it.size } == replacement.explicitParameters.size) {
|
require(parametersStructure.sumOf { it.valueParameters.size } == replacement.explicitParameters.size) {
|
||||||
"Wrong value parameters structure: $parametersStructure"
|
"Wrong value parameters structure: $parametersStructure"
|
||||||
}
|
}
|
||||||
val old2newList = original.explicitParameters.zip(
|
val old2newList = original.explicitParameters.zip(
|
||||||
parametersStructure.scan(0) { partial: Int, templates: List<ValueParameterTemplate> -> partial + templates.size }
|
parametersStructure.scan(0) { partial: Int, templates: RemappedParameter -> partial + templates.valueParameters.size }
|
||||||
.zipWithNext { start: Int, finish: Int -> replacement.explicitParameters.slice(start until finish) }
|
.zipWithNext { start: Int, finish: Int -> replacement.explicitParameters.slice(start until finish) }
|
||||||
)
|
)
|
||||||
for ((param, newParamList) in old2newList) {
|
for (i in old2newList.indices) {
|
||||||
val single = newParamList.singleOrNull()
|
val (param, newParamList) = old2newList[i]
|
||||||
if (single != null) {
|
when (val structure = parametersStructure[i]) {
|
||||||
valueDeclarationsRemapper.remapSymbol(param.symbol, single)
|
is MultiFieldValueClassMapping ->
|
||||||
} else {
|
valueDeclarationsRemapper.remapSymbol(param.symbol, newParamList.map { VirtualProperty(it) }, structure.declarations)
|
||||||
valueDeclarationsRemapper.remapSymbol(param.symbol, newParamList.map { VirtualProperty(it) })
|
is RegularMapping -> valueDeclarationsRemapper.remapSymbol(param.symbol, newParamList.single())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -352,7 +391,8 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
|
|||||||
val initializersStatements = valueClass.declarations.filterIsInstance<IrAnonymousInitializer>().flatMap { it.body.statements }
|
val initializersStatements = valueClass.declarations.filterIsInstance<IrAnonymousInitializer>().flatMap { it.body.statements }
|
||||||
valueDeclarationsRemapper.remapSymbol(
|
valueDeclarationsRemapper.remapSymbol(
|
||||||
oldPrimaryConstructor.constructedClass.thisReceiver!!.symbol,
|
oldPrimaryConstructor.constructedClass.thisReceiver!!.symbol,
|
||||||
primaryConstructorImpl.valueParameters.map { VirtualProperty(it) }
|
primaryConstructorImpl.valueParameters.map { VirtualProperty(it) },
|
||||||
|
this,
|
||||||
)
|
)
|
||||||
primaryConstructorImpl.body = context.createIrBuilder(primaryConstructorImpl.symbol).irBlockBody {
|
primaryConstructorImpl.body = context.createIrBuilder(primaryConstructorImpl.symbol).irBlockBody {
|
||||||
for (stmt in initializersStatements) {
|
for (stmt in initializersStatements) {
|
||||||
@@ -472,8 +512,9 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
|
|||||||
val parameter2expression = typedArgumentList(originalFunction, original)
|
val parameter2expression = typedArgumentList(originalFunction, original)
|
||||||
val structure = replacements.bindingParameterTemplateStructure[originalFunction]!!
|
val structure = replacements.bindingParameterTemplateStructure[originalFunction]!!
|
||||||
require(parameter2expression.size == structure.size)
|
require(parameter2expression.size == structure.size)
|
||||||
require(structure.sumOf { it.size } == replacement.explicitParametersCount)
|
require(structure.sumOf { it.valueParameters.size } == replacement.explicitParametersCount)
|
||||||
val newArguments: List<IrExpression?> = makeNewArguments(parameter2expression.map { (_, argument) -> argument }, structure)
|
val newArguments: List<IrExpression?> =
|
||||||
|
makeNewArguments(parameter2expression.map { (_, argument) -> argument }, structure.map { it.valueParameters })
|
||||||
+irCall(replacement.symbol).apply {
|
+irCall(replacement.symbol).apply {
|
||||||
copyTypeArgumentsFrom(original)
|
copyTypeArgumentsFrom(original)
|
||||||
for ((parameter, argument) in replacement.explicitParameters zip newArguments) {
|
for ((parameter, argument) in replacement.explicitParameters zip newArguments) {
|
||||||
@@ -586,7 +627,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
|
|||||||
initializer?.let {
|
initializer?.let {
|
||||||
flattenExpressionTo(it, variables.toGettersAndSetters())
|
flattenExpressionTo(it, variables.toGettersAndSetters())
|
||||||
}
|
}
|
||||||
valueDeclarationsRemapper.remapSymbol(declaration.symbol, variables.map { VirtualProperty(it) })
|
valueDeclarationsRemapper.remapSymbol(declaration.symbol, variables.map { VirtualProperty(it) }, declarations)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return super.visitVariable(declaration)
|
return super.visitVariable(declaration)
|
||||||
|
|||||||
+2
-2
@@ -10,10 +10,10 @@ import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
|||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.getRequiresMangling
|
||||||
import org.jetbrains.kotlin.backend.jvm.hasMangledReturnType
|
import org.jetbrains.kotlin.backend.jvm.hasMangledReturnType
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.eraseTypeParameters
|
import org.jetbrains.kotlin.backend.jvm.ir.eraseTypeParameters
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.needsAccessor
|
import org.jetbrains.kotlin.backend.jvm.ir.needsAccessor
|
||||||
import org.jetbrains.kotlin.backend.jvm.requiresMangling
|
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
@@ -222,7 +222,7 @@ class JvmPropertiesLowering(private val backendContext: JvmBackendContext) : IrE
|
|||||||
val getter = property.getter
|
val getter = property.getter
|
||||||
if (getter != null) {
|
if (getter != null) {
|
||||||
val needsMangling =
|
val needsMangling =
|
||||||
getter.extensionReceiverParameter?.type?.requiresMangling == true ||
|
getter.extensionReceiverParameter?.type?.getRequiresMangling(includeInline = true, includeMFVC = false) == true ||
|
||||||
(state.functionsWithInlineClassReturnTypesMangled && getter.hasMangledReturnType)
|
(state.functionsWithInlineClassReturnTypesMangled && getter.hasMangledReturnType)
|
||||||
val mangled = if (needsMangling) inlineClassReplacements.getReplacementFunction(getter) else null
|
val mangled = if (needsMangling) inlineClassReplacements.getReplacementFunction(getter) else null
|
||||||
defaultMethodSignatureMapper.mapFunctionName(mangled ?: getter)
|
defaultMethodSignatureMapper.mapFunctionName(mangled ?: getter)
|
||||||
|
|||||||
+68
-9
@@ -7,21 +7,21 @@ package org.jetbrains.kotlin.backend.jvm.lower
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.copyParameterDeclarationsFrom
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.pop
|
import org.jetbrains.kotlin.backend.common.pop
|
||||||
import org.jetbrains.kotlin.backend.common.push
|
import org.jetbrains.kotlin.backend.common.push
|
||||||
import org.jetbrains.kotlin.backend.jvm.InlineClassAbi
|
import org.jetbrains.kotlin.backend.jvm.*
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.ir.isInlineClassType
|
||||||
import org.jetbrains.kotlin.backend.jvm.MemoizedValueClassAbstractReplacements
|
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
|
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||||
import org.jetbrains.kotlin.ir.builders.irReturn
|
import org.jetbrains.kotlin.ir.builders.irReturn
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.transformStatement
|
import org.jetbrains.kotlin.ir.transformStatement
|
||||||
import org.jetbrains.kotlin.ir.util.constructedClass
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
internal abstract class JvmValueClassAbstractLowering(val context: JvmBackendContext) : FileLoweringPass,
|
internal abstract class JvmValueClassAbstractLowering(val context: JvmBackendContext) : FileLoweringPass,
|
||||||
@@ -121,7 +121,7 @@ internal abstract class JvmValueClassAbstractLowering(val context: JvmBackendCon
|
|||||||
|
|
||||||
val bridgeFunction = createBridgeFunction(function, replacement)
|
val bridgeFunction = createBridgeFunction(function, replacement)
|
||||||
|
|
||||||
return listOfNotNull(replacement, bridgeFunction)
|
return listOf(replacement, bridgeFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
final override fun visitReturn(expression: IrReturn): IrExpression {
|
final override fun visitReturn(expression: IrReturn): IrExpression {
|
||||||
@@ -166,10 +166,69 @@ internal abstract class JvmValueClassAbstractLowering(val context: JvmBackendCon
|
|||||||
super.visitAnonymousInitializerNew(declaration)
|
super.visitAnonymousInitializerNew(declaration)
|
||||||
|
|
||||||
protected abstract fun addBindingsFor(original: IrFunction, replacement: IrFunction)
|
protected abstract fun addBindingsFor(original: IrFunction, replacement: IrFunction)
|
||||||
protected abstract fun createBridgeFunction(function: IrSimpleFunction, replacement: IrSimpleFunction): IrSimpleFunction?
|
|
||||||
|
private fun createBridgeFunction(
|
||||||
|
function: IrSimpleFunction,
|
||||||
|
replacement: IrSimpleFunction
|
||||||
|
): IrSimpleFunction {
|
||||||
|
val bridgeFunction = createBridgeDeclaration(
|
||||||
|
function,
|
||||||
|
when {
|
||||||
|
// If the original function has signature which need mangling we still need to replace it with a mangled version.
|
||||||
|
(!function.isFakeOverride || function.findInterfaceImplementation(context.state.jvmDefaultMode) != null) &&
|
||||||
|
function.signatureRequiresMangling() ->
|
||||||
|
replacement.name
|
||||||
|
// Since we remove the corresponding property symbol from the bridge we need to resolve getter/setter
|
||||||
|
// names at this point.
|
||||||
|
replacement.isGetter ->
|
||||||
|
Name.identifier(JvmAbi.getterName(replacement.correspondingPropertySymbol!!.owner.name.asString()))
|
||||||
|
replacement.isSetter ->
|
||||||
|
Name.identifier(JvmAbi.setterName(replacement.correspondingPropertySymbol!!.owner.name.asString()))
|
||||||
|
else ->
|
||||||
|
function.name
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Update the overridden symbols to point to their inline class replacements
|
||||||
|
bridgeFunction.overriddenSymbols = replacement.overriddenSymbols
|
||||||
|
|
||||||
|
// Replace the function body with a wrapper
|
||||||
|
if (bridgeFunction.isFakeOverride && bridgeFunction.parentAsClass.isSpecificLoweringLogicApplicable()) {
|
||||||
|
// Fake overrides redirect from the replacement to the original function, which is in turn replaced during interfacePhase.
|
||||||
|
createBridgeBody(replacement, bridgeFunction, function, true)
|
||||||
|
} else {
|
||||||
|
createBridgeBody(bridgeFunction, replacement, function, false)
|
||||||
|
}
|
||||||
|
return bridgeFunction
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrSimpleFunction.signatureRequiresMangling() =
|
||||||
|
fullValueParameterList.any { it.type.getRequiresMangling() } ||
|
||||||
|
context.state.functionsWithInlineClassReturnTypesMangled && returnType.getRequiresMangling() && returnType.isInlineClassType()
|
||||||
|
|
||||||
protected fun typedArgumentList(function: IrFunction, expression: IrMemberAccessExpression<*>) = listOfNotNull(
|
protected fun typedArgumentList(function: IrFunction, expression: IrMemberAccessExpression<*>) = listOfNotNull(
|
||||||
function.dispatchReceiverParameter?.let { it to expression.dispatchReceiver },
|
function.dispatchReceiverParameter?.let { it to expression.dispatchReceiver },
|
||||||
function.extensionReceiverParameter?.let { it to expression.extensionReceiver }
|
function.extensionReceiverParameter?.let { it to expression.extensionReceiver }
|
||||||
) + function.valueParameters.map { it to expression.getValueArgument(it.index) }
|
) + function.valueParameters.map { it to expression.getValueArgument(it.index) }
|
||||||
|
|
||||||
|
|
||||||
|
// We may need to add a bridge method for inline class methods with static replacements. Ideally, we'd do this in BridgeLowering,
|
||||||
|
// but unfortunately this is a special case in the old backend. The bridge method is not marked as such and does not follow the normal
|
||||||
|
// visibility rules for bridge methods.
|
||||||
|
private fun createBridgeDeclaration(source: IrSimpleFunction, mangledName: Name) =
|
||||||
|
context.irFactory.buildFun {
|
||||||
|
updateFrom(source)
|
||||||
|
name = mangledName
|
||||||
|
returnType = source.returnType
|
||||||
|
}.apply {
|
||||||
|
copyParameterDeclarationsFrom(source)
|
||||||
|
annotations = source.annotations
|
||||||
|
parent = source.parent
|
||||||
|
// We need to ensure that this bridge has the same attribute owner as its static inline class replacement, since this
|
||||||
|
// is used in [CoroutineCodegen.isStaticInlineClassReplacementDelegatingCall] to identify the bridge and avoid generating
|
||||||
|
// a continuation class.
|
||||||
|
copyAttributes(source)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun createBridgeBody(source: IrSimpleFunction, target: IrSimpleFunction, original: IrFunction, inverted: Boolean)
|
||||||
}
|
}
|
||||||
+1
-1
@@ -370,7 +370,7 @@ private class SyntheticAccessorTransformer(
|
|||||||
|
|
||||||
val constructedClass = constructedClass
|
val constructedClass = constructedClass
|
||||||
|
|
||||||
if (!DescriptorVisibilities.isPrivate(visibility) && !constructedClass.isSingleFieldValueClass && hasMangledParameters &&
|
if (!DescriptorVisibilities.isPrivate(visibility) && !constructedClass.isValue && hasMangledParameters() &&
|
||||||
!constructedClass.isAnonymousObject
|
!constructedClass.isAnonymousObject
|
||||||
) return true
|
) return true
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ object InlineClassAbi {
|
|||||||
): String? =
|
): String? =
|
||||||
collectFunctionSignatureForManglingSuffix(
|
collectFunctionSignatureForManglingSuffix(
|
||||||
useOldMangleRules,
|
useOldMangleRules,
|
||||||
valueParameters.any { it.requiresMangling },
|
valueParameters.any { it.getRequiresMangling() },
|
||||||
// The JVM backend computes mangled names after creating suspend function views, but before default argument
|
// The JVM backend computes mangled names after creating suspend function views, but before default argument
|
||||||
// stub insertion. It would be nice if this part of the continuation lowering happened earlier in the pipeline.
|
// stub insertion. It would be nice if this part of the continuation lowering happened earlier in the pipeline.
|
||||||
// TODO: Move suspend function view creation before JvmInlineClassLowering.
|
// TODO: Move suspend function view creation before JvmInlineClassLowering.
|
||||||
@@ -124,19 +124,28 @@ object InlineClassAbi {
|
|||||||
get() = (this as IrSimpleFunction).correspondingPropertySymbol!!.owner.name
|
get() = (this as IrSimpleFunction).correspondingPropertySymbol!!.owner.name
|
||||||
}
|
}
|
||||||
|
|
||||||
val IrType.requiresMangling: Boolean
|
fun IrType.getRequiresMangling(includeInline: Boolean = true, includeMFVC: Boolean = true): Boolean {
|
||||||
get() {
|
val irClass = erasedUpperBound
|
||||||
val irClass = erasedUpperBound
|
return irClass.fqNameWhenAvailable != StandardNames.RESULT_FQ_NAME && when {
|
||||||
return irClass.isValue && irClass.fqNameWhenAvailable != StandardNames.RESULT_FQ_NAME
|
irClass.isSingleFieldValueClass -> includeInline
|
||||||
|
irClass.isMultiFieldValueClass -> includeMFVC
|
||||||
|
else -> false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val IrFunction.fullValueParameterList: List<IrValueParameter>
|
val IrFunction.fullValueParameterList: List<IrValueParameter>
|
||||||
get() = listOfNotNull(extensionReceiverParameter) + valueParameters
|
get() = listOfNotNull(extensionReceiverParameter) + valueParameters
|
||||||
|
|
||||||
val IrFunction.hasMangledParameters: Boolean
|
fun IrFunction.hasMangledParameters(includeInline: Boolean = true, includeMFVC: Boolean = true): Boolean =
|
||||||
get() = dispatchReceiverParameter != null && parentAsClass.isValue ||
|
(dispatchReceiverParameter != null && when {
|
||||||
fullValueParameterList.any { it.type.requiresMangling } ||
|
parentAsClass.isSingleFieldValueClass -> includeInline
|
||||||
(this is IrConstructor && constructedClass.isValue)
|
parentAsClass.isMultiFieldValueClass -> includeMFVC
|
||||||
|
else -> false
|
||||||
|
}) || fullValueParameterList.any { it.type.getRequiresMangling(includeInline, includeMFVC) } || (this is IrConstructor && when {
|
||||||
|
constructedClass.isSingleFieldValueClass -> includeInline
|
||||||
|
constructedClass.isMultiFieldValueClass -> includeMFVC
|
||||||
|
else -> false
|
||||||
|
})
|
||||||
|
|
||||||
val IrFunction.hasMangledReturnType: Boolean
|
val IrFunction.hasMangledReturnType: Boolean
|
||||||
get() = returnType.isInlineClassType() && parentClassOrNull?.isFileClass != true
|
get() = returnType.isInlineClassType() && parentClassOrNull?.isFileClass != true
|
||||||
|
|||||||
+3
-2
@@ -40,7 +40,7 @@ class MemoizedInlineClassReplacements(
|
|||||||
private val storageManager = LockBasedStorageManager("inline-class-replacements")
|
private val storageManager = LockBasedStorageManager("inline-class-replacements")
|
||||||
|
|
||||||
val originalFunctionForStaticReplacement: MutableMap<IrFunction, IrFunction> = ConcurrentHashMap()
|
val originalFunctionForStaticReplacement: MutableMap<IrFunction, IrFunction> = ConcurrentHashMap()
|
||||||
internal val originalFunctionForMethodReplacement: MutableMap<IrFunction, IrFunction> = ConcurrentHashMap()
|
val originalFunctionForMethodReplacement: MutableMap<IrFunction, IrFunction> = ConcurrentHashMap()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a replacement for a function or a constructor.
|
* Get a replacement for a function or a constructor.
|
||||||
@@ -76,7 +76,8 @@ class MemoizedInlineClassReplacements(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, mangle functions with mangled parameters, ignoring constructors
|
// Otherwise, mangle functions with mangled parameters, ignoring constructors
|
||||||
it is IrSimpleFunction && !it.isFromJava() && (it.hasMangledParameters || mangleReturnTypes && it.hasMangledReturnType) ->
|
it is IrSimpleFunction && !it.isFromJava() &&
|
||||||
|
(it.hasMangledParameters(includeMFVC = false) || mangleReturnTypes && it.hasMangledReturnType) ->
|
||||||
createMethodReplacement(it)
|
createMethodReplacement(it)
|
||||||
|
|
||||||
else ->
|
else ->
|
||||||
|
|||||||
+33
-16
@@ -35,9 +35,9 @@ class MemoizedMultiFieldValueClassReplacements(
|
|||||||
) : MemoizedValueClassAbstractReplacements(irFactory, context) {
|
) : MemoizedValueClassAbstractReplacements(irFactory, context) {
|
||||||
private val storageManager = LockBasedStorageManager("multi-field-value-class-replacements")
|
private val storageManager = LockBasedStorageManager("multi-field-value-class-replacements")
|
||||||
|
|
||||||
internal val originalFunctionForStaticReplacement: MutableMap<IrFunction, IrFunction> = ConcurrentHashMap()
|
val originalFunctionForStaticReplacement: MutableMap<IrFunction, IrFunction> = ConcurrentHashMap()
|
||||||
internal val originalFunctionForMethodReplacement: MutableMap<IrFunction, IrFunction> = ConcurrentHashMap()
|
val originalFunctionForMethodReplacement: MutableMap<IrFunction, IrFunction> = ConcurrentHashMap()
|
||||||
internal val originalConstructorForConstructorReplacement: MutableMap<IrConstructor, IrConstructor> = ConcurrentHashMap()
|
private val originalConstructorForConstructorReplacement: MutableMap<IrConstructor, IrConstructor> = ConcurrentHashMap()
|
||||||
|
|
||||||
val getDeclarations: (IrClass) -> MultiFieldValueClassSpecificDeclarations? =
|
val getDeclarations: (IrClass) -> MultiFieldValueClassSpecificDeclarations? =
|
||||||
storageManager.createMemoizedFunctionWithNullableValues {
|
storageManager.createMemoizedFunctionWithNullableValues {
|
||||||
@@ -77,24 +77,24 @@ class MemoizedMultiFieldValueClassReplacements(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrFunction.makeValueParametersFromTemplate(newFlattenedParameters: List<List<ValueParameterTemplate>>) =
|
private fun IrFunction.makeValueParametersFromTemplate(newFlattenedParameters: List<RemappedParameter>) = newFlattenedParameters
|
||||||
newFlattenedParameters.flatten().mapIndexed { index: Int, template -> template.toParameter(this, index) }
|
.flatMap { it.valueParameters }.mapIndexed { index: Int, template -> template.toParameter(this, index) }
|
||||||
|
|
||||||
private fun List<ValueParameterTemplate>.grouped(
|
private fun List<ValueParameterTemplate>.grouped(
|
||||||
originWhenFlattenedAndNotSpecified: IrDeclarationOrigin? = IrDeclarationOrigin.GENERATED_MULTI_FIELD_VALUE_CLASS_PARAMETER
|
originWhenFlattenedAndNotSpecified: IrDeclarationOrigin? = IrDeclarationOrigin.GENERATED_MULTI_FIELD_VALUE_CLASS_PARAMETER
|
||||||
): List<List<ValueParameterTemplate>> = map { parameter ->
|
): List<RemappedParameter> = map { parameter ->
|
||||||
val declaration = parameter.type.takeIf { !it.isNullable() }?.getClass()?.let { getDeclarations(it) }
|
val declarations = parameter.type.takeIf { !it.isNullable() }?.getClass()?.let { getDeclarations(it) }
|
||||||
?: return@map listOf(parameter)
|
?: return@map RemappedParameter.RegularMapping(parameter)
|
||||||
require(!parameter.original.hasDefaultValue()) { "Default parameters values are not supported for multi-field value classes" }
|
require(!parameter.original.hasDefaultValue()) { "Default parameters values are not supported for multi-field value classes" }
|
||||||
declaration.leaves.map { leaf ->
|
RemappedParameter.MultiFieldValueClassMapping(declarations, declarations.leaves.map { leaf ->
|
||||||
ValueParameterTemplate(
|
ValueParameterTemplate(
|
||||||
name = "${parameter.name}$${declaration.nodeFullNames[leaf]!!}",
|
name = "${parameter.name}$${declarations.nodeFullNames[leaf]!!}",
|
||||||
type = leaf.type,
|
type = leaf.type,
|
||||||
origin = parameter.origin ?: originWhenFlattenedAndNotSpecified,
|
origin = parameter.origin ?: originWhenFlattenedAndNotSpecified,
|
||||||
defaultValue = null,
|
defaultValue = null,
|
||||||
original = parameter.original,
|
original = parameter.original,
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildReplacement(
|
private fun buildReplacement(
|
||||||
@@ -115,8 +115,8 @@ class MemoizedMultiFieldValueClassReplacements(
|
|||||||
|
|
||||||
private fun makeGroupedValueParametersFrom(
|
private fun makeGroupedValueParametersFrom(
|
||||||
function: IrFunction, includeDispatcherReceiver: Boolean
|
function: IrFunction, includeDispatcherReceiver: Boolean
|
||||||
): List<List<ValueParameterTemplate>> {
|
): List<RemappedParameter> {
|
||||||
val newFlattenedParameters = mutableListOf<List<ValueParameterTemplate>>()
|
val newFlattenedParameters = mutableListOf<RemappedParameter>()
|
||||||
if (function.dispatchReceiverParameter != null && includeDispatcherReceiver) {
|
if (function.dispatchReceiverParameter != null && includeDispatcherReceiver) {
|
||||||
val template = ValueParameterTemplate(
|
val template = ValueParameterTemplate(
|
||||||
name = "\$dispatchReceiver",
|
name = "\$dispatchReceiver",
|
||||||
@@ -161,7 +161,24 @@ class MemoizedMultiFieldValueClassReplacements(
|
|||||||
return newFlattenedParameters
|
return newFlattenedParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
val bindingParameterTemplateStructure: MutableMap<IrFunction, List<List<ValueParameterTemplate>>> = ConcurrentHashMap()
|
sealed class RemappedParameter {
|
||||||
|
data class RegularMapping(val valueParameter: ValueParameterTemplate) : RemappedParameter() {
|
||||||
|
override val valueParameters: List<ValueParameterTemplate> = listOf(valueParameter)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class MultiFieldValueClassMapping(
|
||||||
|
val declarations: MultiFieldValueClassSpecificDeclarations,
|
||||||
|
override val valueParameters: List<ValueParameterTemplate>,
|
||||||
|
) : RemappedParameter() {
|
||||||
|
init {
|
||||||
|
require(valueParameters.size > 1) { "MFVC must have > 1 fields" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract val valueParameters: List<ValueParameterTemplate>
|
||||||
|
}
|
||||||
|
|
||||||
|
val bindingParameterTemplateStructure: MutableMap<IrFunction, List<RemappedParameter>> = ConcurrentHashMap()
|
||||||
|
|
||||||
override fun createStaticReplacement(function: IrFunction): IrSimpleFunction =
|
override fun createStaticReplacement(function: IrFunction): IrSimpleFunction =
|
||||||
buildReplacement(function, JvmLoweredDeclarationOrigin.STATIC_MULTI_FIELD_VALUE_CLASS_REPLACEMENT, noFakeOverride = true) {
|
buildReplacement(function, JvmLoweredDeclarationOrigin.STATIC_MULTI_FIELD_VALUE_CLASS_REPLACEMENT, noFakeOverride = true) {
|
||||||
@@ -184,7 +201,7 @@ class MemoizedMultiFieldValueClassReplacements(
|
|||||||
original = receiver,
|
original = receiver,
|
||||||
) else null
|
) else null
|
||||||
bindingParameterTemplateStructure[function] =
|
bindingParameterTemplateStructure[function] =
|
||||||
if (receiverTemplate != null) listOf(listOf(receiverTemplate)) + newFlattenedParameters else newFlattenedParameters
|
if (receiverTemplate != null) listOf(RemappedParameter.RegularMapping(receiverTemplate)) + newFlattenedParameters else newFlattenedParameters
|
||||||
valueParameters = makeValueParametersFromTemplate(newFlattenedParameters)
|
valueParameters = makeValueParametersFromTemplate(newFlattenedParameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +234,7 @@ class MemoizedMultiFieldValueClassReplacements(
|
|||||||
defaultValue = receiver.defaultValue,
|
defaultValue = receiver.defaultValue,
|
||||||
original = receiver
|
original = receiver
|
||||||
)
|
)
|
||||||
bindingParameterTemplateStructure[function] = listOf(listOf(receiverTemplate))
|
bindingParameterTemplateStructure[function] = listOf(RemappedParameter.RegularMapping(receiverTemplate))
|
||||||
return newGetter
|
return newGetter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+24
-3
@@ -35,8 +35,12 @@ value class E(val x: D) {
|
|||||||
set(_) = TODO()
|
set(_) = TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Base3 {
|
||||||
|
val z: E
|
||||||
|
}
|
||||||
|
|
||||||
@JvmInline
|
@JvmInline
|
||||||
value class R<T : Any>(val x: Int, val y: UInt, val z: E, val t: A<T>)
|
value class R<T : Any>(val x: Int, val y: UInt, override val z: E, val t: A<T>): Base1, Base3
|
||||||
|
|
||||||
fun <T : List<Int>> f(r: R<T>) {
|
fun <T : List<Int>> f(r: R<T>) {
|
||||||
println(r)
|
println(r)
|
||||||
@@ -79,7 +83,20 @@ fun h1() {
|
|||||||
println(y)
|
println(y)
|
||||||
}
|
}
|
||||||
|
|
||||||
class NotInlined(var l: R<List<Int>>, var y: Int) {
|
interface Base1 {
|
||||||
|
val fakeOverrideMFVC: R<List<Int>>
|
||||||
|
get() = TODO()
|
||||||
|
val fakeOverrideRegular: Int
|
||||||
|
get() = TODO()
|
||||||
|
}
|
||||||
|
interface Base2 {
|
||||||
|
var l: R<List<Int>>
|
||||||
|
}
|
||||||
|
interface Base4<T> {
|
||||||
|
var l: T
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotInlined(override var l: R<List<Int>>, var y: Int): Base1, Base2, Base4<R<List<Int>>> {
|
||||||
override fun toString(): String = l.toString() + l.z.x.x.z
|
override fun toString(): String = l.toString() + l.z.x.x.z
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -119,7 +136,7 @@ class NotInlined(var l: R<List<Int>>, var y: Int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ekeke(x: NotInlined) {
|
fun testVars(x: NotInlined) {
|
||||||
x.l.toString()
|
x.l.toString()
|
||||||
var y = x.l
|
var y = x.l
|
||||||
y.toString()
|
y.toString()
|
||||||
@@ -129,6 +146,10 @@ fun ekeke(x: NotInlined) {
|
|||||||
x.l = R<List<Int>>(x.l.x, x.l.y, x.l.z, x.l.t)
|
x.l = R<List<Int>>(x.l.x, x.l.y, x.l.z, x.l.t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun reuseBoxed(list: MutableList<R<List<Int>>>) {
|
||||||
|
list.add(list.last())
|
||||||
|
}
|
||||||
|
|
||||||
// todo add default parameters
|
// todo add default parameters
|
||||||
|
|
||||||
fun box() = "bad"//.also { h(R(1, 2U, E(D(C(3, B(4U), "5"))), A(listOf(listOf(6))))) }
|
fun box() = "bad"//.also { h(R(1, 2U, E(D(C(3, B(4U), "5"))), A(listOf(listOf(6))))) }
|
||||||
|
|||||||
Reference in New Issue
Block a user