[IR] Unify MFVC bridge redirection, fix related bugs, support MFVC overriding functions with default parameters

#KT-1179
This commit is contained in:
Evgeniy.Zhelenskiy
2023-04-22 08:44:09 +02:00
committed by Space Team
parent 384ed9cc9e
commit bf5fa61ffb
28 changed files with 577 additions and 433 deletions
@@ -52095,6 +52095,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/valueClasses/mutableSharedMfvcVar.kt");
}
@Test
@TestMetadata("nothingAsParameterType.kt")
public void testNothingAsParameterType() throws Exception {
runTest("compiler/testData/codegen/box/valueClasses/nothingAsParameterType.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
}
@Test
@TestMetadata("overrideFunctionWithDefaultParameter.kt")
public void testOverrideFunctionWithDefaultParameter() throws Exception {
@@ -52095,6 +52095,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/valueClasses/mutableSharedMfvcVar.kt");
}
@Test
@TestMetadata("nothingAsParameterType.kt")
public void testNothingAsParameterType() throws Exception {
runTest("compiler/testData/codegen/box/valueClasses/nothingAsParameterType.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
}
@Test
@TestMetadata("overrideFunctionWithDefaultParameter.kt")
public void testOverrideFunctionWithDefaultParameter() throws Exception {
@@ -5,11 +5,10 @@
package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedString
import org.jetbrains.kotlin.backend.common.ir.ValueRemapper
import org.jetbrains.kotlin.backend.common.lower.isMovedReceiver
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
@@ -30,6 +29,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
import org.jetbrains.kotlin.backend.common.lower.isMovedReceiver as isMovedReceiverImpl
// TODO: fix expect/actual default parameters
@@ -263,8 +263,11 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
protected val forceSetOverrideSymbols: Boolean = true,
) : IrElementTransformerVoid(), BodyLoweringPass {
private val declarationStack = mutableListOf<IrDeclaration>()
override fun lower(irBody: IrBody, container: IrDeclaration) {
declarationStack.push(container)
irBody.transformChildrenVoid(this)
declarationStack.pop()
}
protected open fun shouldReplaceWithSyntheticFunction(functionAccess: IrFunctionAccessExpression): Boolean {
@@ -275,50 +278,44 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
if (!shouldReplaceWithSyntheticFunction(expression))
return expression
val (symbol, params) = parametersForCall(expression) ?: return expression
val symbol = createStubFunction(expression) ?: return expression
for (i in 0 until expression.typeArgumentsCount) {
log { "$symbol[$i]: ${expression.getTypeArgument(i)}" }
}
symbol.owner.typeParameters.forEach { log { "${symbol.owner}[${it.index}] : $it" } }
val stubFunction = symbol.owner
stubFunction.typeParameters.forEach { log { "$stubFunction[${it.index}] : $it" } }
val isStatic = isStatic(expression.symbol.owner)
val newCall = builder(symbol).apply {
copyTypeArgumentsFrom(expression)
var receivers = 0
if (isStatic) {
if (symbol.owner.dispatchReceiverParameter != null) {
dispatchReceiver = params[receivers++]
val declaration = expression.symbol.owner
val currentDeclaration = declarationStack.last()
return context.createIrBuilder(
currentDeclaration.symbol, startOffset = expression.startOffset, endOffset = expression.endOffset
).irBlock {
val newCall = builder(symbol).apply {
val offset = if (needsTypeArgumentOffset(declaration)) declaration.parentAsClass.typeParameters.size else 0
for (i in 0 until typeArgumentsCount) {
putTypeArgument(i, expression.getTypeArgument(i + offset))
}
if (symbol.owner.extensionReceiverParameter != null) {
extensionReceiver = params[receivers++]
val parameter2arguments = argumentsForCall(expression, stubFunction)
for ((parameter, argument) in parameter2arguments) {
when (parameter) {
stubFunction.dispatchReceiverParameter -> log { "call::dispatch@: ${ir2string(argument)}" }
stubFunction.extensionReceiverParameter -> log { "call::extension@: ${ir2string(argument)}" }
else -> log { "call::params@$${parameter.index}/${parameter.name}: ${ir2string(argument)}" }
}
if (argument != null) {
putArgument(parameter, argument)
}
}
} else {
dispatchReceiver = expression.dispatchReceiver
extensionReceiver = expression.extensionReceiver
}
params.drop(receivers).forEachIndexed { i, value ->
log { "call::params@$i/${symbol.owner.valueParameters[i].name}: ${ir2string(value)}" }
putValueArgument(i, value)
}
log { "call::extension@: ${ir2string(expression.extensionReceiver)}" }
log { "call::dispatch@: ${ir2string(expression.dispatchReceiver)}" }
}
return newCall.takeIf { it.type == expression.type } ?: IrTypeOperatorCallImpl(
startOffset = newCall.startOffset,
endOffset = newCall.endOffset,
type = expression.type,
operator = IrTypeOperator.IMPLICIT_CAST,
typeOperand = expression.type,
argument = newCall
)
+irCastIfNeeded(newCall, expression.type)
}.unwrapBlock()
}
private fun needsTypeArgumentOffset(declaration: IrFunction) =
isStatic(declaration) && declaration.parentAsClass.isMultiFieldValueClass && declaration is IrSimpleFunction
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
expression.transformChildrenVoid()
return visitFunctionAccessExpression(expression) {
@@ -362,11 +359,13 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
override fun visitCall(expression: IrCall): IrExpression {
expression.transformChildrenVoid()
val declaration = expression.symbol.owner
val typeParametersToRemove = if (needsTypeArgumentOffset(declaration)) declaration.parentAsClass.typeParameters.size else 0
with(expression) {
return visitFunctionAccessExpression(expression) {
IrCallImpl(
startOffset, endOffset, (it as IrSimpleFunctionSymbol).owner.returnType, it,
typeArgumentsCount = typeArgumentsCount,
typeArgumentsCount = typeArgumentsCount - typeParametersToRemove,
valueArgumentsCount = it.owner.valueParameters.size,
origin = LoweredStatementOrigins.DEFAULT_DISPATCH_CALL,
superQualifierSymbol = superQualifierSymbol
@@ -375,9 +374,7 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
}
}
open protected fun parametersForCall(expression: IrFunctionAccessExpression): Pair<IrFunctionSymbol, List<IrExpression?>>? {
val startOffset = expression.startOffset
val endOffset = expression.endOffset
private fun createStubFunction(expression: IrFunctionAccessExpression): IrFunctionSymbol? {
val declaration = expression.symbol.owner
// We *have* to find the actual function here since on the JVM, a default stub for a function implemented
@@ -396,8 +393,14 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
baseFunction.copyAnnotations(),
)
} ?: return null
log { "$declaration -> $stubFunction" }
return stubFunction.symbol
}
protected open fun IrBlockBuilder.argumentsForCall(expression: IrFunctionAccessExpression, stubFunction: IrFunction): Map<IrValueParameter, IrExpression?> {
val startOffset = expression.startOffset
val endOffset = expression.endOffset
val declaration = expression.symbol.owner
val realArgumentsNumber = declaration.valueParameters.filterNot { it.isMovedReceiver() }.size
val maskValues = IntArray((realArgumentsNumber + 31) / 32)
@@ -408,32 +411,48 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
}
var sourceParameterIndex = -1
val valueParametersPrefix =
if (isStatic(declaration))
return buildMap {
val valueParametersPrefix: List<IrValueParameter> = if (isStatic(declaration)) {
listOfNotNull(stubFunction.dispatchReceiverParameter, stubFunction.extensionReceiverParameter)
else emptyList()
return stubFunction.symbol to (valueParametersPrefix + stubFunction.valueParameters).mapIndexed { i, parameter ->
if (!parameter.isMovedReceiver() && parameter != stubFunction.dispatchReceiverParameter && parameter != stubFunction.extensionReceiverParameter) {
++sourceParameterIndex
} else {
stubFunction.dispatchReceiverParameter?.let { put(it, expression.dispatchReceiver) }
stubFunction.extensionReceiverParameter?.let { put(it, expression.extensionReceiver) }
listOf()
}
when {
sourceParameterIndex >= realArgumentsNumber + maskValues.size -> IrConstImpl.constNull(startOffset, endOffset, parameter.type)
sourceParameterIndex >= realArgumentsNumber -> IrConstImpl.int(startOffset, endOffset, parameter.type, maskValues[sourceParameterIndex - realArgumentsNumber])
else -> {
val valueArgument = expression.getValueArgument(i)
if (valueArgument == null) {
maskValues[sourceParameterIndex / 32] = maskValues[sourceParameterIndex / 32] or (1 shl (sourceParameterIndex % 32))
}
valueArgument ?: nullConst(startOffset, endOffset, parameter)?.let {
IrCompositeImpl(
expression.startOffset,
expression.endOffset,
parameter.type,
IrStatementOrigin.DEFAULT_VALUE,
listOf(it)
)
for ((i, parameter) in (valueParametersPrefix + stubFunction.valueParameters).withIndex()) {
if (!parameter.isMovedReceiver() && parameter != stubFunction.dispatchReceiverParameter && parameter != stubFunction.extensionReceiverParameter) {
++sourceParameterIndex
}
val newArgument = when {
sourceParameterIndex >= realArgumentsNumber + maskValues.size -> IrConstImpl.constNull(
startOffset,
endOffset,
parameter.type
)
sourceParameterIndex >= realArgumentsNumber -> IrConstImpl.int(
startOffset,
endOffset,
parameter.type,
maskValues[sourceParameterIndex - realArgumentsNumber]
)
else -> {
val valueArgument = expression.getValueArgument(i)
if (valueArgument == null) {
maskValues[sourceParameterIndex / 32] =
maskValues[sourceParameterIndex / 32] or (1 shl (sourceParameterIndex % 32))
}
valueArgument ?: nullConst(startOffset, endOffset, parameter)?.let {
IrCompositeImpl(
expression.startOffset,
expression.endOffset,
parameter.type,
IrStatementOrigin.DEFAULT_VALUE,
listOf(it)
)
}
}
}
put(parameter, newArgument)
}
}
}
@@ -455,6 +474,8 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
protected open fun isStatic(function: IrFunction): Boolean = false
private fun log(msg: () -> String) = context.log { "DEFAULT-INJECTOR: ${msg()}" }
protected fun IrValueParameter.isMovedReceiver() = isMovedReceiverImpl()
}
// Remove default argument initializers.
@@ -374,6 +374,7 @@ class InlineClassLowering(val context: CommonBackendContext) {
function.parent,
function.toInlineClassImplementationName(),
function,
typeParametersFromContext = extractTypeParameters(function.parentAsClass)
typeParametersFromContext = extractTypeParameters(function.parentAsClass),
remapMultiFieldValueClassStructure = context::remapMultiFieldValueClassStructure
)
}
@@ -5,14 +5,15 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.backend.common.lower.DefaultParameterInjector
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
import org.jetbrains.kotlin.ir.backend.js.JsStatementOrigins
import org.jetbrains.kotlin.ir.backend.js.export.isExported
import org.jetbrains.kotlin.ir.backend.js.utils.getVoid
import org.jetbrains.kotlin.ir.backend.js.utils.jsConstructorReference
import org.jetbrains.kotlin.ir.builders.IrBlockBuilder
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.expressions.IrCall
@@ -20,8 +21,6 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.util.copyAnnotations
import org.jetbrains.kotlin.ir.util.isTopLevel
import org.jetbrains.kotlin.ir.util.isVararg
@@ -48,32 +47,24 @@ class JsDefaultParameterInjector(context: JsIrBackendContext) :
}
}
override fun parametersForCall(expression: IrFunctionAccessExpression): Pair<IrFunctionSymbol, List<IrExpression?>>? {
override fun IrBlockBuilder.argumentsForCall(expression: IrFunctionAccessExpression, stubFunction: IrFunction): Map<IrValueParameter, IrExpression?> {
val startOffset = expression.startOffset
val endOffset = expression.endOffset
val declaration = expression.symbol.owner
val stubFunction = factory.findBaseFunctionWithDefaultArgumentsFor(declaration, skipInline, skipExternalMethods)?.let {
factory.generateDefaultsFunction(
it,
skipInline,
skipExternalMethods,
forceSetOverrideSymbols,
defaultArgumentStubVisibility(declaration),
useConstructorMarker(declaration),
it.copyAnnotations(),
)
} ?: return null
return stubFunction.symbol to buildList {
return buildMap {
stubFunction.dispatchReceiverParameter?.let { put(it, expression.dispatchReceiver) }
stubFunction.extensionReceiverParameter?.let { put(it, expression.extensionReceiver) }
for (i in 0 until expression.valueArgumentsCount) {
val declaredParameter = stubFunction.valueParameters[i]
val actualParameter = expression.getValueArgument(i)
add(actualParameter ?: nullConst(startOffset, endOffset, declaredParameter))
val actualArgument = expression.getValueArgument(i)
put(declaredParameter, actualArgument ?: nullConst(startOffset, endOffset, declaredParameter))
}
if (expression is IrCall && stubFunction.hasSuperContextParameter()) {
add(expression.superQualifierSymbol?.prototypeOf() ?: context.getVoid())
put(
stubFunction.valueParameters[expression.valueArgumentsCount],
expression.superQualifierSymbol?.prototypeOf() ?: this@JsDefaultParameterInjector.context.getVoid()
)
}
}
}
@@ -226,7 +226,8 @@ private class AddContinuationLowering(context: JvmBackendContext) : SuspendLower
JavaDescriptorVisibilities.PACKAGE_VISIBILITY,
isFakeOverride = false,
copyMetadata = false,
typeParametersFromContext = extractTypeParameters(irFunction.parentAsClass)
typeParametersFromContext = extractTypeParameters(irFunction.parentAsClass),
remapMultiFieldValueClassStructure = context::remapMultiFieldValueClassStructure
)
static.body = irFunction.moveBodyTo(static)
// Fixup dispatch parameter to outer class
@@ -10,9 +10,10 @@ import org.jetbrains.kotlin.backend.common.lower.SpecialMethodWithDefaultInfo
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irNot
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.*
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.MultiFieldValueClassMapping
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.RegularMapping
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements
import org.jetbrains.kotlin.backend.jvm.SpecialBridge
import org.jetbrains.kotlin.backend.jvm.ir.*
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
@@ -24,7 +25,10 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isNullable
import org.jetbrains.kotlin.ir.types.isPrimitiveType
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.name.Name
@@ -598,22 +602,20 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass
bridge: IrSimpleFunction,
target: IrSimpleFunction,
superQualifierSymbol: IrClassSymbol? = null
) =
irCastIfNeeded(irBlock {
+irReturn(irCall(target, origin = IrStatementOrigin.BRIDGE_DELEGATION, superQualifierSymbol = superQualifierSymbol).apply {
val targetStructure = getStructure(target)
val bridgeStructure = getStructure(bridge)
if (targetStructure == null && bridgeStructure == null) {
for ((param, targetParam) in bridge.explicitParameters.zip(target.explicitParameters)) {
putArgument(targetParam, irGetOrCast(bridge, param, targetParam))
) = irCastIfNeeded(irBlock {
+irReturn(irCall(target, origin = IrStatementOrigin.BRIDGE_DELEGATION, superQualifierSymbol = superQualifierSymbol).apply {
if (getStructure(target) == null && getStructure(bridge) == null) {
for ((param, targetParam) in bridge.explicitParameters.zip(target.explicitParameters)) {
val argument = irGet(param).let { argument ->
if (param == bridge.dispatchReceiverParameter) argument else irCastIfNeeded(argument, targetParam.type.upperBound)
}
} else {
this@irBlock.addBoxedAndUnboxedMfvcArguments(targetStructure, bridgeStructure, target, bridge, this)
putArgument(targetParam, argument)
}
})
}.unwrapBlock(), bridge.returnType.upperBound)
} else {
this@irBlock.addBoxedAndUnboxedMfvcArguments(target, bridge, this)
}
})
}.unwrapBlock(), bridge.returnType.upperBound)
private fun getStructure(function: IrSimpleFunction): List<MemoizedMultiFieldValueClassReplacements.RemappedParameter>? {
val structure = context.multiFieldValueClassReplacements.bindingNewFunctionToParameterTemplateStructure[function] ?: return null
@@ -625,106 +627,22 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass
}
private fun IrBlockBuilder.addBoxedAndUnboxedMfvcArguments(
targetStructure: List<MemoizedMultiFieldValueClassReplacements.RemappedParameter>?,
bridgeStructure: List<MemoizedMultiFieldValueClassReplacements.RemappedParameter>?,
target: IrSimpleFunction,
bridge: IrSimpleFunction,
irCall: IrCall
) {
require(
targetStructure == null || bridgeStructure == null ||
bridgeStructure.size == targetStructure.size &&
(targetStructure zip bridgeStructure).none { (targetParameter, bridgeParameter) ->
targetParameter is MultiFieldValueClassMapping && bridgeParameter is MultiFieldValueClassMapping &&
targetParameter.rootMfvcNode != bridgeParameter.rootMfvcNode
}
) { "Incompatible structures: $bridgeStructure and $targetStructure" }
val targetExplicitParameters = target.explicitParameters
val bridgeExplicitParameters = bridge.explicitParameters
var targetIndex = 0
var bridgeIndex = 0
var structureIndex = 0
while (targetIndex < targetExplicitParameters.size && bridgeIndex < bridgeExplicitParameters.size) {
val targetRemappedParameter = targetStructure?.get(structureIndex)
val bridgeRemappedParameter = bridgeStructure?.get(structureIndex)
when (targetRemappedParameter) {
is MultiFieldValueClassMapping -> when (bridgeRemappedParameter) {
is MultiFieldValueClassMapping -> {
require(bridgeRemappedParameter.rootMfvcNode == targetRemappedParameter.rootMfvcNode) {
"Incompatible parameters: $bridgeRemappedParameter, $targetRemappedParameter"
}
repeat(bridgeRemappedParameter.valueParameters.size) {
val bridgeParameter = bridgeExplicitParameters[bridgeIndex++]
val targetParameter = targetExplicitParameters[targetIndex++]
irCall.putArgument(targetParameter, irGetOrCast(bridge, bridgeParameter, targetParameter))
}
}
is RegularMapping, null -> {
val bridgeParameter = bridgeExplicitParameters[bridgeIndex++]
val targetParameterType = targetRemappedParameter.rootMfvcNode.mfvc.defaultType
val instance = targetRemappedParameter.rootMfvcNode.createInstanceFromBox(
this,
irCastIfNeeded(irGet(bridgeParameter), targetParameterType),
AccessType.ChooseEffective
) { error("Not applicable") }
val newArguments = instance.makeFlattenedGetterExpressions(this, bridge.parentAsClass, registerPossibleExtraBoxCreation = {})
for (newArgument in newArguments) {
irCall.putArgument(targetExplicitParameters[targetIndex++], newArgument)
}
}
}
is RegularMapping, null -> {
val targetParameter = targetExplicitParameters[targetIndex]
when (bridgeRemappedParameter) {
is MultiFieldValueClassMapping -> {
val valueArguments = List(bridgeRemappedParameter.rootMfvcNode.leavesCount) {
irGet(bridgeExplicitParameters[bridgeIndex++])
}
val boxCall = bridgeRemappedParameter.rootMfvcNode.makeBoxedExpression(
this, bridgeRemappedParameter.typeArguments, valueArguments, registerPossibleExtraBoxCreation = {}
)
irCall.putArgument(targetParameter, irCastIfNeeded(boxCall, targetParameter.type.upperBound))
}
is RegularMapping, null -> {
val bridgeParameter = bridgeExplicitParameters[bridgeIndex++]
irCall.putArgument(targetParameter, irGetOrCast(bridge, bridgeParameter, targetParameter))
}
}
targetIndex++
}
val parameters2arguments = this@BridgeLowering.context.multiFieldValueClassReplacements
.mapFunctionMfvcStructures(this, target, bridge) { sourceParameter, targetParameterType ->
if (sourceParameter == bridge.dispatchReceiverParameter) irGet(sourceParameter)
else irCastIfNeeded(irGet(sourceParameter), targetParameterType)
}
for ((parameter, argument) in parameters2arguments) {
if (argument != null) {
irCall.putArgument(parameter, argument)
}
structureIndex++
}
require(targetIndex == targetExplicitParameters.size && bridgeIndex == bridgeExplicitParameters.size) {
"Incorrect bridge:\n${bridge.dump()}\n\nfor target\n${target.dump()}"
}
require((targetStructure == null || structureIndex == targetStructure.size)) {
"Invalid structure index $structureIndex for $targetStructure"
}
require((bridgeStructure == null || structureIndex == bridgeStructure.size)) {
"Invalid structure index $structureIndex for $bridgeStructure"
}
}
private fun IrBuilderWithScope.irGetOrCast(
bridge: IrSimpleFunction,
bridgeParameter: IrValueParameter,
targetParameter: IrValueParameter
) =
irGet(bridgeParameter).let { argument ->
if (bridgeParameter == bridge.dispatchReceiverParameter)
argument
else
irCastIfNeeded(argument, targetParameter.type.upperBound)
}
private fun IrBuilderWithScope.irCastIfNeeded(expression: IrExpression, to: IrType): IrExpression =
if (expression.type == to || to.isAny() || to.isNullableAny()) expression else irImplicitCast(expression, to)
private val IrFunction.jvmMethod: Method
get() = context.bridgeLoweringCache.computeJvmMethod(this)
}
@@ -12,26 +12,20 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.MultiFieldValueClassMapping
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.RegularMapping
import org.jetbrains.kotlin.backend.jvm.fullValueParameterList
import org.jetbrains.kotlin.backend.jvm.ir.*
import org.jetbrains.kotlin.backend.jvm.makeBoxedExpression
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.builders.irBlockBody
import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.builders.irReturn
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.expressions.putArgument
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.*
@@ -96,59 +90,27 @@ private class InheritedDefaultMethodsOnClassesLowering(val context: JvmBackendCo
val classStartOffset = classOverride.parentAsClass.startOffset
val backendContext = context
context.createIrBuilder(irFunction.symbol, classStartOffset, classStartOffset).apply {
irFunction.body = irBlockBody {
+irReturn(
irCall(defaultImplFun.symbol, irFunction.returnType).apply {
superMethod.parentAsClass.typeParameters.forEachIndexed { index, _ ->
putTypeArgument(index, createPlaceholderAnyNType(context.irBuiltIns))
}
passTypeArgumentsFrom(irFunction, offset = superMethod.parentAsClass.typeParameters.size)
irFunction.dispatchReceiverParameter?.let {
putValueArgument(0, irGet(it).reinterpretAsDispatchReceiverOfType(superClassType))
}
val bindingNewFunctionToParameterTemplateStructure = backendContext.multiFieldValueClassReplacements
.bindingNewFunctionToParameterTemplateStructure
val structure = bindingNewFunctionToParameterTemplateStructure[classOverride]?.let { structure ->
require(structure.sumOf { it.valueParameters.size } == classOverride.explicitParametersCount) {
"Bad parameters structure: $structure"
}
if (defaultImplFun.explicitParametersCount == irFunction.explicitParametersCount) {
null
} else {
require(structure.size == defaultImplFun.explicitParametersCount) { "Bad parameters structure: $structure" }
structure
}
}
require(structure == null || structure.first() is RegularMapping) {
"Dispatch receiver for method replacement cannot be flattened"
}
val sourceFullValueParameterList = irFunction.fullValueParameterList
if (structure == null) {
for ((index, parameter) in sourceFullValueParameterList.withIndex()) {
putValueArgument(1 + index, irGet(parameter))
}
} else {
var flattenedIndex = 0
for (i in 1 until structure.size) {
when (val remappedParameter = structure[i]) {
is MultiFieldValueClassMapping -> {
val valueArguments = remappedParameter.valueParameters.indices.map {
irGet(sourceFullValueParameterList[flattenedIndex++])
}
val boxedExpression = remappedParameter.rootMfvcNode.makeBoxedExpression(
this@irBlockBody, remappedParameter.typeArguments, valueArguments, registerPossibleExtraBoxCreation = {}
)
putValueArgument(i, boxedExpression)
}
is RegularMapping -> putValueArgument(i, irGet(sourceFullValueParameterList[flattenedIndex++]))
}
}
irFunction.body = irExprBody(irBlock {
val parameter2arguments = backendContext.multiFieldValueClassReplacements
.mapFunctionMfvcStructures(this, defaultImplFun, irFunction) { sourceParameter, _ ->
irGet(sourceParameter).let {
if (sourceParameter != irFunction.dispatchReceiverParameter) it
else it.reinterpretAsDispatchReceiverOfType(superClassType)
}
}
)
}
+irCall(defaultImplFun.symbol, irFunction.returnType).apply {
for (index in superMethod.parentAsClass.typeParameters.indices) {
putTypeArgument(index, createPlaceholderAnyNType(context.irBuiltIns))
}
passTypeArgumentsFrom(irFunction, offset = superMethod.parentAsClass.typeParameters.size)
for ((parameter, argument) in parameter2arguments) {
if (argument != null) {
putArgument(parameter, argument)
}
}
}
})
}
return irFunction
@@ -10,11 +10,18 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.ir.defaultValue
import org.jetbrains.kotlin.backend.jvm.ir.getJvmVisibilityOfDefaultArgumentStub
import org.jetbrains.kotlin.ir.builders.IrBlockBuilder
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.explicitParametersCount
import org.jetbrains.kotlin.ir.util.render
class JvmDefaultParameterInjector(context: JvmBackendContext) : DefaultParameterInjector<JvmBackendContext>(
context = context,
@@ -40,4 +47,57 @@ class JvmDefaultParameterInjector(context: JvmBackendContext) : DefaultParameter
override fun isStatic(function: IrFunction): Boolean =
function.origin == JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_REPLACEMENT ||
function.origin == JvmLoweredDeclarationOrigin.STATIC_MULTI_FIELD_VALUE_CLASS_REPLACEMENT
override fun IrBlockBuilder.argumentsForCall(
expression: IrFunctionAccessExpression, stubFunction: IrFunction
): Map<IrValueParameter, IrExpression?> {
val startOffset = expression.startOffset
val endOffset = expression.endOffset
val declaration = expression.symbol.owner
val realArgumentsNumber = declaration.valueParameters.filterNot { it.isMovedReceiver() }.size
val maskValues = IntArray((realArgumentsNumber + 31) / 32)
val oldArguments: Map<IrValueParameter, IrExpression?> = buildMap {
declaration.dispatchReceiverParameter?.let { put(it, expression.dispatchReceiver) }
declaration.extensionReceiverParameter?.let { put(it, expression.extensionReceiver) }
putAll(declaration.valueParameters.mapIndexed { index, parameter -> parameter to expression.getValueArgument(index) })
}
val indexes = declaration.valueParameters.filterNot { it.isMovedReceiver() }.withIndex().associate { it.value to it.index }
val mainArguments = this@JvmDefaultParameterInjector.context.multiFieldValueClassReplacements
.mapFunctionMfvcStructures(this, stubFunction, declaration) { sourceParameter: IrValueParameter, targetParameterType: IrType ->
val valueArgument = oldArguments[sourceParameter]
if (valueArgument == null) {
val index = indexes[sourceParameter]!!
maskValues[index / 32] = maskValues[index / 32] or (1 shl (index % 32))
}
valueArgument ?: IrCompositeImpl(
expression.startOffset,
expression.endOffset,
targetParameterType,
IrStatementOrigin.DEFAULT_VALUE,
listOf(nullConst(startOffset, endOffset, targetParameterType))
)
}
assert(stubFunction.explicitParametersCount - mainArguments.size - maskValues.size in listOf(0, 1)) {
"argument count mismatch: expected $realArgumentsNumber arguments + ${maskValues.size} masks + optional handler/marker, " +
"got ${stubFunction.explicitParametersCount} total in ${stubFunction.render()}"
}
return buildMap {
putAll(mainArguments)
val restParameters = stubFunction.valueParameters.filterNot { it in mainArguments }
for ((maskParameter, maskValue) in restParameters zip maskValues.asList()) {
put(maskParameter, IrConstImpl.int(startOffset, endOffset, maskParameter.type, maskValue))
}
if (restParameters.size > maskValues.size) {
val lastParameter = restParameters.last()
put(lastParameter, IrConstImpl.constNull(startOffset, endOffset, lastParameter.type))
}
}
}
}
@@ -518,15 +518,21 @@ internal class JvmMultiFieldValueClassLowering(
name = mangledName
returnType = source.returnType
}.apply {
val isAnyOverriddenReplaced = replacement.overriddenSymbols.any {
it.owner in replacements.bindingNewFunctionToParameterTemplateStructure
val implementationStructure = if (isFakeOverride) {
val superDeclaration = replacement.allOverridden().singleOrNull { it.body != null }
?: error("${this.render()} is fake override and has no implementation")
replacements.bindingNewFunctionToParameterTemplateStructure[superDeclaration]
?: superDeclaration.explicitParameters.map { RegularMapping(it) }
} else {
replacements.bindingNewFunctionToParameterTemplateStructure[replacement]
?: error("${replacement.render()} must have MFVC structure")
}
if (source.parentAsClass.isMultiFieldValueClass && isAnyOverriddenReplaced) {
copyTypeParametersFrom(source) // without static type parameters
val substitutionMap = makeTypeParameterSubstitutionMap(source, this)
dispatchReceiverParameter = source.dispatchReceiverParameter!!.let { // source!!!
it.copyTo(this, type = it.type.substitute(substitutionMap))
}
copyTypeParametersFrom(source) // without static type parameters
val substitutionMap = makeTypeParameterSubstitutionMap(source, this)
dispatchReceiverParameter = source.dispatchReceiverParameter!!.let { // source!!!
it.copyTo(this, type = it.type.substitute(substitutionMap))
}
if ((source.parent as? IrClass)?.isMultiFieldValueClass == true) {
require(replacement.dispatchReceiverParameter == null) {
"""
Ambiguous receivers:
@@ -534,19 +540,32 @@ internal class JvmMultiFieldValueClassLowering(
${replacement.dispatchReceiverParameter!!.render()}
""".trimIndent()
}
require(replacement.extensionReceiverParameter == null) {
"Static replacement must have no extension receiver but ${replacement.extensionReceiverParameter!!.render()} found"
}
val replacementStructure = replacements.bindingNewFunctionToParameterTemplateStructure[replacement]!!
val offset = replacementStructure[0].valueParameters.size
valueParameters = replacement.valueParameters.drop(offset).map {
it.copyTo(this, type = it.type.substitute(substitutionMap), index = it.index - offset)
}
val parametersMapping = (replacement.valueParameters.drop(offset) zip valueParameters).toMap()
context.remapMultiFieldValueClassStructure(replacement, this, parametersMapping)
} else {
copyParameterDeclarationsFrom(source)
}
require(replacement.extensionReceiverParameter == null) {
"Static replacement must have no extension receiver but ${replacement.extensionReceiverParameter!!.render()} found"
}
val structure = buildList(implementationStructure.size) {
var valueParameterIndex = 0
add(RegularMapping(dispatchReceiverParameter!!))
val valueParametersAsMutableList = mutableListOf<IrValueParameter>()
for (expectedParameterStructure in implementationStructure.asSequence().drop(this.size)) {
fun IrValueParameter.copy() =
copyTo(this@apply, type = type.substitute(substitutionMap), index = valueParameterIndex++)
val parameterStructure = when (expectedParameterStructure) {
is RegularMapping -> RegularMapping(expectedParameterStructure.valueParameter.copy())
is MultiFieldValueClassMapping -> MultiFieldValueClassMapping(
expectedParameterStructure.rootMfvcNode,
substitutionMap,
expectedParameterStructure.valueParameters.map { it.copy() }
)
}
add(parameterStructure)
valueParametersAsMutableList.addAll(parameterStructure.valueParameters)
}
valueParameters = valueParametersAsMutableList
}
replacements.bindingNewFunctionToParameterTemplateStructure[this] = structure
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
@@ -557,110 +576,17 @@ internal class JvmMultiFieldValueClassLowering(
override fun createBridgeBody(source: IrSimpleFunction, target: IrSimpleFunction, original: IrFunction, inverted: Boolean) {
allScopes.push(createScope(source))
source.body = context.createJvmIrBuilder(source.symbol).run {
val sourceExplicitParameters = source.explicitParameters
val targetExplicitParameters = target.explicitParameters
source.body = with(context.createJvmIrBuilder(source.symbol)) {
irExprBody(irBlock {
val parameters2arguments = replacements.mapFunctionMfvcStructures(this, target, source) { sourceParameter, _ ->
irGet(sourceParameter)
}
+irReturn(irCall(target).apply {
passTypeArgumentsWithOffsets(target, source) { source.typeParameters[it].defaultType }
val sourceStructure: List<RemappedParameter>? = replacements.bindingNewFunctionToParameterTemplateStructure[source]
val targetStructure: List<RemappedParameter>? = replacements.bindingNewFunctionToParameterTemplateStructure[target]
val errorMessage = {
"""
Incompatible structures for
Source: $sourceStructure
${source.render()}
Target: $targetStructure
${target.render()}
""".trimIndent()
}
when (targetStructure) {
null -> when (sourceStructure) {
null -> require(targetExplicitParameters.size == sourceExplicitParameters.size, errorMessage)
else -> {
require(targetExplicitParameters.size == sourceStructure.size, errorMessage)
require(sourceExplicitParameters.size == sourceStructure.sumOf { it.valueParameters.size }, errorMessage)
}
for ((parameter, argument) in parameters2arguments) {
if (argument != null) {
putArgument(parameter, argument)
}
else -> when (sourceStructure) {
null -> {
require(targetStructure.size == sourceExplicitParameters.size, errorMessage)
require(targetStructure.sumOf { it.valueParameters.size } == targetExplicitParameters.size, errorMessage)
}
else -> {
require(targetStructure.size == sourceStructure.size, errorMessage)
require(sourceStructure.sumOf { it.valueParameters.size } == sourceExplicitParameters.size, errorMessage)
require(targetStructure.sumOf { it.valueParameters.size } == targetExplicitParameters.size, errorMessage)
require((targetStructure zip sourceStructure).none { (t, s) ->
t is MultiFieldValueClassMapping && s is MultiFieldValueClassMapping && t.rootMfvcNode != s.rootMfvcNode
}, errorMessage)
}
}
}
val structuresSizes = sourceStructure?.size ?: targetStructure?.size ?: targetExplicitParameters.size
var flattenedSourceIndex = 0
var flattenedTargetIndex = 0
for (i in 0 until structuresSizes) {
val remappedSourceParameter = sourceStructure?.get(i)
val remappedTargetParameter = targetStructure?.get(i)
when (remappedSourceParameter) {
is MultiFieldValueClassMapping -> {
when (remappedTargetParameter) {
is MultiFieldValueClassMapping -> {
require(remappedTargetParameter.valueParameters.size == remappedSourceParameter.valueParameters.size) {
"Incompatible structures: $remappedTargetParameter, $remappedSourceParameter"
}
repeat(remappedTargetParameter.valueParameters.size) {
putArgument(
targetExplicitParameters[flattenedTargetIndex++],
irGet(sourceExplicitParameters[flattenedSourceIndex++])
)
}
}
is RegularMapping, null -> {
val valueArguments = sourceExplicitParameters
.slice(flattenedSourceIndex until flattenedSourceIndex + remappedSourceParameter.valueParameters.size)
.map { irGet(it) }
val targetParameter = targetExplicitParameters[flattenedTargetIndex++]
val boxedExpression = remappedSourceParameter.rootMfvcNode.makeBoxedExpression(
this@irBlock,
remappedSourceParameter.typeArguments,
valueArguments,
::registerPossibleExtraBoxUsage
)
putArgument(targetParameter, boxedExpression)
.also { flattenedSourceIndex += remappedSourceParameter.valueParameters.size }
}
}
}
is RegularMapping, null -> when (remappedTargetParameter) {
is MultiFieldValueClassMapping -> {
val receiver = sourceExplicitParameters[flattenedSourceIndex++]
val rootNode = remappedTargetParameter.rootMfvcNode
val instance = rootNode.createInstanceFromBox(
this@irBlock, irGet(receiver), AccessType.ChooseEffective, ::variablesSaver,
)
val flattenedExpressions = instance.makeFlattenedGetterExpressions(
this@irBlock, irCurrentClass, ::registerPossibleExtraBoxUsage
)
for (expression in flattenedExpressions) {
putArgument(targetExplicitParameters[flattenedTargetIndex++], expression)
}
}
else -> putArgument(
targetExplicitParameters[flattenedTargetIndex++],
irGet(sourceExplicitParameters[flattenedSourceIndex++])
)
}
}
}
require(flattenedTargetIndex == targetExplicitParameters.size && flattenedSourceIndex == sourceExplicitParameters.size) {
"Incorrect source:\n${source.dump()}\n\nfor target\n${target.dump()}"
}
})
})
@@ -1076,7 +1002,9 @@ internal class JvmMultiFieldValueClassLowering(
originalFunction: IrFunction,
original: IrMemberAccessExpression<*>,
replacement: IrFunction,
makeMemberAccessExpression: (IrFunctionSymbol) -> IrMemberAccessExpression<*> = ::irCall,
makeMemberAccessExpression: (IrFunctionSymbol) -> IrMemberAccessExpression<*> = { callee: IrFunctionSymbol ->
irCall(callee.owner, superQualifierSymbol = (original as? IrCall)?.superQualifierSymbol)
},
): IrMemberAccessExpression<*> {
val parameter2expression = typedArgumentList(originalFunction, original)
val structure = replacements.bindingOldFunctionToParameterTemplateStructure[originalFunction]!!
@@ -1302,6 +1230,9 @@ internal class JvmMultiFieldValueClassLowering(
if (expression is IrConstructorCall) expression.symbol.owner.constructedClass else expression.type.erasedUpperBound
)
val type = if (expression is IrConstructorCall) expression.symbol.owner.constructedClass.defaultType else expression.type
if (type == context.irBuiltIns.nothingType) {
return flattenExpressionTo(irImplicitCast(expression, instance.type), instance)
}
val lowering = this@JvmMultiFieldValueClassLowering
if (rootNode == null || !type.needsMfvcFlattening() || instance.size == 1) {
require(instance.size == 1) { "Required 1 variable/field to store regular value but got ${instance.size}" }
@@ -211,7 +211,7 @@ internal abstract class JvmValueClassAbstractLowering(
}
)
// Update the overridden symbols to point to their inline class replacements
// Update the overridden symbols to point to their value class replacements
bridgeFunction.overriddenSymbols = replacement.overriddenSymbols
// Replace the function body with a wrapper
@@ -80,6 +80,11 @@ private class StaticDefaultFunctionLowering(val context: JvmBackendContext) : Ir
private fun getStaticFunctionWithReceivers(function: IrSimpleFunction): IrSimpleFunction =
context.staticDefaultStubs.getOrPut(function.symbol) {
context.irFactory.createStaticFunctionWithReceivers(function.parent, function.name, function)
context.irFactory.createStaticFunctionWithReceivers(
function.parent,
function.name,
function,
remapMultiFieldValueClassStructure = context::remapMultiFieldValueClassStructure
)
}
}
@@ -220,7 +220,8 @@ class JvmCachedDeclarations(
modality = Modality.OPEN,
visibility = defaultImplsVisibility,
isFakeOverride = false,
typeParametersFromContext = parent.typeParameters
typeParametersFromContext = parent.typeParameters,
remapMultiFieldValueClassStructure = context::remapMultiFieldValueClassStructure
).also {
it.copyCorrespondingPropertyFrom(interfaceFun)
@@ -257,7 +258,6 @@ class JvmCachedDeclarations(
defaultImplsRedirections.getOrPut(fakeOverride) {
assert(fakeOverride.isFakeOverride)
val irClass = fakeOverride.parentAsClass
val mfvcReplacementStructure = context.multiFieldValueClassReplacements.bindingNewFunctionToParameterTemplateStructure
val redirectFunction = context.irFactory.buildFun {
origin = JvmLoweredDeclarationOrigin.SUPER_INTERFACE_METHOD_BRIDGE
name = fakeOverride.name
@@ -282,7 +282,7 @@ class JvmCachedDeclarations(
annotations = fakeOverride.annotations
copyCorrespondingPropertyFrom(fakeOverride)
}
mfvcReplacementStructure[fakeOverride]?.let { mfvcReplacementStructure[redirectFunction] = it }
context.remapMultiFieldValueClassStructure(fakeOverride, redirectFunction, parametersMappingOrNull = null)
redirectFunction
}
@@ -5,23 +5,32 @@
package org.jetbrains.kotlin.backend.jvm
import org.jetbrains.kotlin.backend.common.lower.parents
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.MultiFieldValueClassMapping
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.RegularMapping
import org.jetbrains.kotlin.backend.jvm.ir.*
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.IrBlockBuilder
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
import org.jetbrains.kotlin.ir.builders.irComposite
import org.jetbrains.kotlin.ir.builders.irExprBody
import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrComposite
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.types.isNothing
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
import java.util.concurrent.ConcurrentHashMap
/**
@@ -43,7 +52,7 @@ class MemoizedMultiFieldValueClassReplacements(
originWhenFlattened: IrDeclarationOrigin,
): RemappedParameter {
val oldParam = this
if (!type.needsMfvcFlattening()) return RemappedParameter.RegularMapping(
if (!type.needsMfvcFlattening()) return RegularMapping(
targetFunction.addValueParameter {
updateFrom(oldParam)
this.name = oldParam.name
@@ -238,7 +247,7 @@ class MemoizedMultiFieldValueClassReplacements(
dispatchReceiverParameter = function.dispatchReceiverParameter?.copyTo(this, index = -1)
val newFlattenedParameters = makeAndAddGroupedValueParametersFrom(function, includeDispatcherReceiver = false, mapOf(), this)
val receiver = dispatchReceiverParameter
return if (receiver != null) listOf(RemappedParameter.RegularMapping(receiver)) + newFlattenedParameters else newFlattenedParameters
return if (receiver != null) listOf(RegularMapping(receiver)) + newFlattenedParameters else newFlattenedParameters
}
/**
@@ -369,4 +378,107 @@ class MemoizedMultiFieldValueClassReplacements(
}
private val IrProperty.backingFieldIfNotToRemove get() = backingField?.takeUnless { it in getFieldsToRemove(this.parentAsClass) }
@Suppress("ClassName")
private object FLATTENED_NOTHING_DEFAULT_VALUE : IrStatementOriginImpl("FLATTENED_NOTHING_DEFAULT_VALUE")
fun mapFunctionMfvcStructures(
irBuilder: IrBlockBuilder,
targetFunction: IrFunction,
sourceFunction: IrFunction,
getArgument: (sourceParameter: IrValueParameter, targetParameterType: IrType) -> IrExpression?
): Map<IrValueParameter, IrExpression?> {
val targetStructure = bindingNewFunctionToParameterTemplateStructure[targetFunction]
?: targetFunction.explicitParameters.map { RegularMapping(it) }
val sourceStructure = bindingNewFunctionToParameterTemplateStructure[sourceFunction]
?: sourceFunction.explicitParameters.map { RegularMapping(it) }
verifyStructureCompatibility(targetStructure, sourceStructure)
return buildMap {
for ((targetParameterStructure, sourceParameterStructure) in targetStructure zip sourceStructure) {
when (targetParameterStructure) {
is RegularMapping -> when (sourceParameterStructure) {
is RegularMapping -> put(
targetParameterStructure.valueParameter,
getArgument(sourceParameterStructure.valueParameter, targetParameterStructure.valueParameter.type)
)
is MultiFieldValueClassMapping -> {
val valueArguments = sourceParameterStructure.valueParameters.map {
getArgument(it, it.type) ?: error("Expected an argument for $sourceParameterStructure")
}
val newArgument =
if (valueArguments.all { it is IrComposite && it.origin == FLATTENED_NOTHING_DEFAULT_VALUE }) {
(valueArguments[0] as IrComposite).statements[0] as IrExpression
} else {
sourceParameterStructure.rootMfvcNode.makeBoxedExpression(
irBuilder,
sourceParameterStructure.typeArguments,
valueArguments,
registerPossibleExtraBoxCreation = {}
)
}
put(targetParameterStructure.valueParameter, newArgument)
}
}
is MultiFieldValueClassMapping -> when (sourceParameterStructure) {
is RegularMapping -> with(irBuilder) {
val argument = getArgument(sourceParameterStructure.valueParameter, targetParameterStructure.boxedType)
?: error("Expected an argument for $sourceParameterStructure")
if (sourceParameterStructure.valueParameter.type.isNothing()) {
for ((index, parameter) in targetParameterStructure.valueParameters.withIndex()) {
put(parameter, irComposite(origin = FLATTENED_NOTHING_DEFAULT_VALUE) {
if (index == 0) +argument
+parameter.type.defaultValue(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, this@MemoizedMultiFieldValueClassReplacements.context
)
})
}
} else {
val instance = targetParameterStructure.rootMfvcNode.createInstanceFromBox(
scope = this,
receiver = argument,
accessType = AccessType.ChooseEffective,
saveVariable = { +it }
)
val arguments = instance.makeFlattenedGetterExpressions(
this, sourceFunction.parents.firstIsInstance<IrClass>(), registerPossibleExtraBoxCreation = {}
)
for ((targetParameter, expression) in targetParameterStructure.valueParameters zip arguments) {
put(targetParameter, expression)
}
}
}
is MultiFieldValueClassMapping -> {
for ((sourceParameter, targetParameter) in sourceParameterStructure.valueParameters zip targetParameterStructure.valueParameters) {
put(targetParameter, getArgument(sourceParameter, targetParameter.type))
}
}
}
}
}
}
}
@OptIn(ExperimentalStdlibApi::class)
private fun verifyStructureCompatibility(
targetStructure: List<RemappedParameter>,
sourceStructure: List<RemappedParameter>
) {
for ((targetParameterStructure, sourceParameterStructure) in targetStructure zip sourceStructure) {
if (targetParameterStructure is MultiFieldValueClassMapping && sourceParameterStructure is MultiFieldValueClassMapping) {
require(targetParameterStructure.rootMfvcNode.mfvc.classId == sourceParameterStructure.rootMfvcNode.mfvc.classId) {
"Incompatible parameter structures:\n$targetParameterStructure inside $targetStructure\n$sourceParameterStructure inside $sourceStructure"
}
}
}
for (extraParameterStructure in targetStructure.slice(sourceStructure.size..<targetStructure.size)) {
require(extraParameterStructure is RegularMapping && extraParameterStructure.valueParameter.origin != IrDeclarationOrigin.DEFINED) {
"Unexpected target MFVC parameter structure:\n$extraParameterStructure inside $targetStructure"
}
}
for (extraParameterStructure in sourceStructure.slice(targetStructure.size..<sourceStructure.size)) {
require(extraParameterStructure is RegularMapping && extraParameterStructure.valueParameter.origin != IrDeclarationOrigin.DEFINED) {
"Unexpected source MFVC parameter structure:\n$extraParameterStructure inside $sourceStructure"
}
}
}
}
@@ -27,10 +27,16 @@ import org.jetbrains.kotlin.name.Name
typealias TypeArguments = Map<IrTypeParameterSymbol, IrType>
/**
* Instance-agnostic tree node describing structure of multi-field value class
*/
sealed interface MfvcNode {
val type: IrType
val leavesCount: Int
/**
* Create instance-specific [ReceiverBasedMfvcNodeInstance] from instance-agnostic [MfvcNode] using a boxed [receiver] as data source.
*/
fun createInstanceFromBox(
scope: IrBlockBuilder,
typeArguments: TypeArguments,
@@ -40,6 +46,9 @@ sealed interface MfvcNode {
): ReceiverBasedMfvcNodeInstance
}
/**
* Create instance-specific [ReceiverBasedMfvcNodeInstance] from instance-agnostic [MfvcNode] using a boxed [receiver] as data source.
*/
fun MfvcNode.createInstanceFromBox(
scope: IrBlockBuilder,
receiver: IrExpression,
@@ -48,10 +57,16 @@ fun MfvcNode.createInstanceFromBox(
) =
createInstanceFromBox(scope, makeTypeArgumentsFromType(receiver.type as IrSimpleType), receiver, accessType, saveVariable)
/**
* Create instance-specific [ValueDeclarationMfvcNodeInstance] from instance-agnostic [MfvcNode] using new flattened variables as data source.
*/
fun MfvcNode.createInstanceFromValueDeclarationsAndBoxType(
scope: IrBuilderWithScope, type: IrSimpleType, name: Name, saveVariable: (IrVariable) -> Unit, isVar: Boolean
): ValueDeclarationMfvcNodeInstance = createInstanceFromValueDeclarations(scope, makeTypeArgumentsFromType(type), name, saveVariable, isVar)
/**
* Create instance-specific [ValueDeclarationMfvcNodeInstance] from instance-agnostic [MfvcNode] using new flattened variables as data source.
*/
fun MfvcNode.createInstanceFromValueDeclarations(
scope: IrBuilderWithScope, typeArguments: TypeArguments, name: Name, saveVariable: (IrVariable) -> Unit, isVar: Boolean
): ValueDeclarationMfvcNodeInstance {
@@ -67,6 +82,9 @@ fun MfvcNode.createInstanceFromValueDeclarations(
return ValueDeclarationMfvcNodeInstance(this, typeArguments, valueDeclarations)
}
/**
* Create instance-specific [ValueDeclarationMfvcNodeInstance] from instance-agnostic [MfvcNode] using flattened [fieldValues] as data source.
*/
fun MfvcNode.createInstanceFromValueDeclarationsAndBoxType(
type: IrSimpleType, fieldValues: List<IrValueDeclaration>
): ValueDeclarationMfvcNodeInstance =
@@ -83,19 +101,41 @@ fun makeTypeArgumentsFromType(type: IrSimpleType): TypeArguments {
}
/**
* Non-root [MfvcNode]. It contains an unbox method and a name.
*/
sealed interface NameableMfvcNode : MfvcNode {
val namedNodeImpl: NameableMfvcNodeImpl
val hasPureUnboxMethod: Boolean
}
/**
* List of names of the root node of the [NameableMfvcNode] up to the node.
*/
val NameableMfvcNode.nameParts: List<Name>
get() = namedNodeImpl.nameParts
/**
* The last [nameParts] which distinguishes the [NameableMfvcNode] from its parent.
*/
val NameableMfvcNode.name: Name
get() = nameParts.last()
/**
* Unbox method of the [NameableMfvcNode].
*/
val NameableMfvcNode.unboxMethod: IrSimpleFunction
get() = namedNodeImpl.unboxMethod
/**
* An unbox function or getter function method name of the [NameableMfvcNode].
*/
val NameableMfvcNode.fullMethodName: Name
get() = namedNodeImpl.fullMethodName
/**
* A field name corresponding to the [NameableMfvcNode].
*/
val NameableMfvcNode.fullFieldName: Name
get() = namedNodeImpl.fullFieldName
@@ -138,7 +178,9 @@ fun MfvcNode.getSubnodeAndIndices(name: Name): Pair<NameableMfvcNode, IntRange>?
val indices = subnodeIndices[node] ?: error("existing node without indices")
return node to indices
}
/**
* Non-leaf [MfvcNode]. It contains a box method and children.
*/
sealed class MfvcNodeWithSubnodes(val subnodes: List<NameableMfvcNode>) : MfvcNode {
abstract override val type: IrSimpleType
abstract val boxMethod: IrSimpleFunction
@@ -159,6 +201,9 @@ sealed class MfvcNodeWithSubnodes(val subnodes: List<NameableMfvcNode>) : MfvcNo
}
}
/**
* Get child by [name].
*/
operator fun get(name: Name): NameableMfvcNode? = mapping[name]
val leaves: List<LeafMfvcNode> = subnodes.leaves
@@ -178,6 +223,9 @@ sealed class MfvcNodeWithSubnodes(val subnodes: List<NameableMfvcNode>) : MfvcNo
}
/**
* Creates a box expression for the given [MfvcNodeWithSubnodes] by calling box methods with the given [typeArguments] and [valueArguments].
*/
fun MfvcNodeWithSubnodes.makeBoxedExpression(
scope: IrBuilderWithScope,
typeArguments: TypeArguments,
@@ -195,6 +243,9 @@ fun MfvcNodeWithSubnodes.makeBoxedExpression(
registerPossibleExtraBoxCreation()
}
/**
* A shortcut to get children by name several times.
*/
operator fun MfvcNodeWithSubnodes.get(names: List<Name>): MfvcNode? {
var cur: MfvcNode = this
for (name in names) {
@@ -267,6 +318,9 @@ private fun validateGettingAccessorParameters(function: IrSimpleFunction) {
require(function.typeParameters.isEmpty()) { "Type parameters are not expected for ${function.render()}" }
}
/**
* [MfvcNode] which corresponds to non-MFVC field which is a field of some MFVC.
*/
class LeafMfvcNode(
override val type: IrType,
methodFullNameMode: MethodFullNameMode,
@@ -310,6 +364,9 @@ val MfvcNode.fields
is LeafMfvcNode -> field?.let(::listOf)
}
/**
* [MfvcNode] which corresponds to MFVC field which is a field of some class.
*/
class IntermediateMfvcNode(
override val type: IrSimpleType,
methodFullNameMode: MethodFullNameMode,
@@ -373,7 +430,9 @@ fun IrSimpleFunction.getGetterField(): IrField? {
val statement = (body?.statements?.singleOrNull() as? IrReturn)?.value as? IrGetField ?: return null
return statement.symbol.owner
}
/**
* [MfvcNode] which corresponds to MFVC itself.
*/
class RootMfvcNode internal constructor(
val mfvc: IrClass,
subnodes: List<NameableMfvcNode>,
@@ -18,29 +18,52 @@ import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.Name
/**
* Instance-specific tree node describing structure of multi-field value class corresponding to the [MfvcNode]
*/
interface MfvcNodeInstance {
val node: MfvcNode
val typeArguments: TypeArguments
val type: IrSimpleType
/**
* Make expressions corresponding to the flattened representation of the [MfvcNodeInstance].
*/
fun makeFlattenedGetterExpressions(
scope: IrBlockBuilder, currentClass: IrClass, registerPossibleExtraBoxCreation: () -> Unit
): List<IrExpression>
/**
* Make expression that corresponds to read access of the instance
*/
fun makeGetterExpression(scope: IrBuilderWithScope, currentClass: IrClass, registerPossibleExtraBoxCreation: () -> Unit): IrExpression
/**
* Get child [MfvcNodeInstance] by [name]
*/
operator fun get(name: Name): MfvcNodeInstance?
fun makeStatements(scope: IrBuilderWithScope, values: List<IrExpression>): List<IrStatement>
/**
* Make setter statements corresponding assignments to the [values] of the given flattened representation.
*/
fun makeSetterStatements(scope: IrBuilderWithScope, values: List<IrExpression>): List<IrStatement>
}
private fun makeTypeFromMfvcNodeAndTypeArguments(node: MfvcNode, typeArguments: TypeArguments) =
node.type.substitute(typeArguments) as IrSimpleType
/**
* Make and add setter statements corresponding assignments to the [values] of the given flattened representation.
*/
fun MfvcNodeInstance.addSetterStatements(scope: IrBlockBuilder, values: List<IrExpression>) = with(scope) {
for (statement in makeStatements(this, values)) {
for (statement in makeSetterStatements(this, values)) {
+statement
}
}
/**
* Make a block of setter statements corresponding assignments to the [values] of the given flattened representation.
*/
fun MfvcNodeInstance.makeSetterExpressions(scope: IrBuilderWithScope, values: List<IrExpression>): IrExpression = scope.irBlock {
addSetterStatements(this, values)
}
@@ -49,6 +72,9 @@ private fun MfvcNodeInstance.checkValuesCount(values: List<IrExpression>) {
require(values.size == node.leavesCount) { "Node $node requires ${node.leavesCount} values but got ${values.map { it.render() }}" }
}
/**
* [MfvcNodeInstance] that stores flattened instance in variables and parameters.
*/
class ValueDeclarationMfvcNodeInstance(
override val node: MfvcNode,
override val typeArguments: TypeArguments,
@@ -77,7 +103,7 @@ class ValueDeclarationMfvcNodeInstance(
return ValueDeclarationMfvcNodeInstance(newNode, typeArguments, valueDeclarations.slice(indices))
}
override fun makeStatements(scope: IrBuilderWithScope, values: List<IrExpression>): List<IrStatement> {
override fun makeSetterStatements(scope: IrBuilderWithScope, values: List<IrExpression>): List<IrStatement> {
checkValuesCount(values)
return valueDeclarations.zip(values) { declaration, value -> scope.irSet(declaration, value) }
}
@@ -143,6 +169,9 @@ fun IrExpression?.isRepeatableAccessor(): Boolean = isRepeatableGetter() || isRe
enum class AccessType { UseFields, ChooseEffective }
/**
* [MfvcNodeInstance] that stores boxed instance in variables and parameters.
*/
class ReceiverBasedMfvcNodeInstance(
private val scope: IrBlockBuilder,
override val node: MfvcNode,
@@ -235,7 +264,7 @@ class ReceiverBasedMfvcNodeInstance(
return newNode.createInstanceFromBox(scope, typeArguments, makeReceiverCopy(), accessType, saveVariable)
}
override fun makeStatements(scope: IrBuilderWithScope, values: List<IrExpression>): List<IrStatement> {
override fun makeSetterStatements(scope: IrBuilderWithScope, values: List<IrExpression>): List<IrStatement> {
checkValuesCount(values)
require(fields != null) { "$node is immutable as it has custom getter and so no backing fields" }
return fields.zip(values) { field, expr -> scope.irSetField(makeReceiverCopy(), field, expr) }
@@ -245,8 +274,6 @@ class ReceiverBasedMfvcNodeInstance(
val MfvcNodeInstance.size: Int
get() = node.leavesCount
fun IrContainerExpression.unwrapBlock(): IrExpression = statements.singleOrNull() as? IrExpression ?: this
/**
* Creates a variable and doesn't add it to a container. It saves the variable with given saveVariable.
*
@@ -110,7 +110,8 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
val newFun = context.irFactory.createStaticFunctionWithReceivers(
function.parent,
name = Name.identifier(function.name.asStringStripSpecialMarkers() + "__externalAdapter"),
function
function,
remapMultiFieldValueClassStructure = context::remapMultiFieldValueClassStructure
)
function.valueParameters.forEachIndexed { index, newParameter ->
@@ -157,7 +158,8 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
val newFun = context.irFactory.createStaticFunctionWithReceivers(
function.parent,
name = Name.identifier(function.name.asStringStripSpecialMarkers() + "__JsExportAdapter"),
function
function,
remapMultiFieldValueClassStructure = context::remapMultiFieldValueClassStructure
)
newFun.valueParameters.forEachIndexed { index, newParameter ->
@@ -7,10 +7,12 @@ package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.*
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
import org.jetbrains.kotlin.ir.builders.declarations.buildReceiverParameter
import org.jetbrains.kotlin.ir.builders.declarations.buildTypeParameter
import org.jetbrains.kotlin.ir.builders.irImplicitCast
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
@@ -1183,7 +1185,8 @@ fun IrFactory.createStaticFunctionWithReceivers(
visibility: DescriptorVisibility = oldFunction.visibility,
isFakeOverride: Boolean = oldFunction.isFakeOverride,
copyMetadata: Boolean = true,
typeParametersFromContext: List<IrTypeParameter> = listOf()
typeParametersFromContext: List<IrTypeParameter> = listOf(),
remapMultiFieldValueClassStructure: (IrFunction, IrFunction, Map<IrValueParameter, IrValueParameter>?) -> Unit
): IrSimpleFunction {
return createFunction(
oldFunction.startOffset, oldFunction.endOffset,
@@ -1271,12 +1274,19 @@ fun IrFactory.createStaticFunctionWithReceivers(
)
}
remapMultiFieldValueClassStructure(oldFunction, this, null)
if (copyMetadata) metadata = oldFunction.metadata
copyAttributes(oldFunction as? IrAttributeContainer)
}
}
fun IrBuilderWithScope.irCastIfNeeded(expression: IrExpression, to: IrType): IrExpression =
if (expression.type == to || to.isAny() || to.isNullableAny()) expression else irImplicitCast(expression, to)
fun IrContainerExpression.unwrapBlock(): IrExpression = statements.singleOrNull() as? IrExpression ?: this
/**
* Appends the parameters in [contextParameters] to the type parameters of
* [this] function, renaming those that may clash with a provided collection of
@@ -0,0 +1,50 @@
// WITH_STDLIB
// WORKS_WHEN_VALUE_CLASS
// LANGUAGE: +ValueClasses
// TARGET_BACKEND: JVM_IR
interface I<T: A> {
fun f(x: T) = println(x)
fun g(x: T = error("OK")) = println(x)
fun T.f(x: T) = println(x)
fun T.g(x: T = error("OK")) = println(x)
}
@JvmInline
value class A(val x: Int, val y: Int): I<Nothing>
@JvmInline
value class B(val x: Int, val y: Int): I<Nothing> {
override fun f(x: Nothing) = println(this)
override fun g(x: Nothing) = println(this)
fun h(x: Nothing) = println(this)
fun t(x: Nothing = error("OK")) = println(this)
override fun Nothing.f(x: Nothing) = println(this@B)
override fun Nothing.g(x: Nothing) = println(this@B)
fun Nothing.h(x: Nothing) = println(this@B)
fun Nothing.t(x: Nothing = error("OK")) = println(this@B)
}
fun box(): String {
require(runCatching { A(1, 2).f(error("OK1")) }.exceptionOrNull()!!.message!! == "OK1")
require(runCatching { B(1, 2).f(error("OK2")) }.exceptionOrNull()!!.message!! == "OK2")
require(runCatching { A(1, 2).g(error("OK3")) }.exceptionOrNull()!!.message!! == "OK3")
require(runCatching { B(1, 2).g(error("OK4")) }.exceptionOrNull()!!.message!! == "OK4")
require(runCatching { A(1, 2).g() }.exceptionOrNull()!!.message!! == "OK")
require(runCatching { B(1, 2).g() }.exceptionOrNull()!!.message!! == "OK")
require(runCatching { B(1, 2).h(error("OK5")) }.exceptionOrNull()!!.message!! == "OK5")
require(runCatching { B(1, 2).t(error("OK6")) }.exceptionOrNull()!!.message!! == "OK6")
require(runCatching { B(1, 2).t() }.exceptionOrNull()!!.message!! == "OK")
require(runCatching { A(1, 2).run { error("OK1").f(error("OK")) } }.exceptionOrNull()!!.message!! == "OK1")
require(runCatching { B(1, 2).run { error("OK2").f(error("OK")) } }.exceptionOrNull()!!.message!! == "OK2")
require(runCatching { A(1, 2).run { error("OK3").g(error("OK")) } }.exceptionOrNull()!!.message!! == "OK3")
require(runCatching { B(1, 2).run { error("OK4").g(error("OK")) } }.exceptionOrNull()!!.message!! == "OK4")
require(runCatching { A(1, 2).run { error("OK5").g() } }.exceptionOrNull()!!.message!! == "OK5")
require(runCatching { B(1, 2).run { error("OK6").g() } }.exceptionOrNull()!!.message!! == "OK6")
require(runCatching { B(1, 2).run { error("OK7").h(error("OK")) } }.exceptionOrNull()!!.message!! == "OK7")
require(runCatching { B(1, 2).run { error("OK8").t(error("OK")) } }.exceptionOrNull()!!.message!! == "OK8")
require(runCatching { B(1, 2).run { error("OK9").t() } }.exceptionOrNull()!!.message!! == "OK9")
return "OK"
}
@@ -2,9 +2,7 @@
// WORKS_WHEN_VALUE_CLASS
// LANGUAGE: +ValueClasses
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM_IR
// Depends on KT-57973
// TARGET_BACKEND: JVM_IR
// JVM_TARGET: 1.8
interface Path {
@@ -2,9 +2,7 @@
// WORKS_WHEN_VALUE_CLASS
// LANGUAGE: +ValueClasses, +GenericInlineClassParameter
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM_IR
// Depends on KT-57973
// TARGET_BACKEND: JVM_IR
// JVM_TARGET: 1.8
interface Path {
+2 -2
View File
@@ -154,11 +154,11 @@ public final class GenericFakeOverrideMFVC {
public method hashCode(): int
public static method hashCode-impl(p0: double, p1: double): int
public synthetic bridge method setP(p0: java.lang.Object): void
public method setP-nuuzChU(@org.jetbrains.annotations.NotNull p0: DPoint): void
public static method setP-nuuzChU(p0: double, p1: double, p2: double, p3: double): void
public method setP-nuuzChU(p0: java.lang.Object): void
public synthetic bridge method setP1(p0: java.lang.Object): void
public method setP1-nuuzChU(@org.jetbrains.annotations.NotNull p0: DPoint): void
public static method setP1-nuuzChU(p0: double, p1: double, p2: double, p3: double): void
public method setP1-nuuzChU(p0: java.lang.Object): void
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
public static method toString-impl(p0: double, p1: double): java.lang.String
public synthetic final method unbox-impl-field1(): double
@@ -154,11 +154,11 @@ public final class GenericFakeOverrideMFVC {
public method hashCode(): int
public static method hashCode-impl(p0: double, p1: double): int
public synthetic bridge method setP(p0: java.lang.Object): void
public method setP-nuuzChU(@org.jetbrains.annotations.NotNull p0: DPoint): void
public static method setP-nuuzChU(p0: double, p1: double, p2: double, p3: double): void
public method setP-nuuzChU(p0: java.lang.Object): void
public synthetic bridge method setP1(p0: java.lang.Object): void
public method setP1-nuuzChU(@org.jetbrains.annotations.NotNull p0: DPoint): void
public static method setP1-nuuzChU(p0: double, p1: double, p2: double, p3: double): void
public method setP1-nuuzChU(p0: java.lang.Object): void
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
public static method toString-impl(p0: double, p1: double): java.lang.String
public synthetic final method unbox-impl-field1(): double
@@ -64,10 +64,10 @@ public final class GenericFakeOverrideMFVC {
public method hashCode(): int
public static method hashCode-impl(p0: java.lang.Object, p1: java.lang.Object): int
public synthetic bridge method setP(p0: java.lang.Object): void
public method setP-E-wHi0Q(@org.jetbrains.annotations.NotNull p0: XPoint): void
public method setP-E-wHi0Q(p0: java.lang.Object): void
public static method setP-E-wHi0Q(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): void
public synthetic bridge method setP1(p0: java.lang.Object): void
public method setP1-E-wHi0Q(@org.jetbrains.annotations.NotNull p0: XPoint): void
public method setP1-E-wHi0Q(p0: java.lang.Object): void
public static method setP1-E-wHi0Q(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): void
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
public static method toString-impl(p0: java.lang.Object, p1: java.lang.Object): java.lang.String
@@ -49328,18 +49328,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@Test
@TestMetadata("overrideFunctionWithDefaultParameter.kt")
public void testOverrideFunctionWithDefaultParameter() throws Exception {
runTest("compiler/testData/codegen/box/valueClasses/overrideFunctionWithDefaultParameter.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
}
@Test
@TestMetadata("overrideFunctionWithDefaultParameterGeneric.kt")
public void testOverrideFunctionWithDefaultParameterGeneric() throws Exception {
runTest("compiler/testData/codegen/box/valueClasses/overrideFunctionWithDefaultParameterGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
}
}
@Nested
@@ -52095,6 +52095,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/valueClasses/mutableSharedMfvcVar.kt");
}
@Test
@TestMetadata("nothingAsParameterType.kt")
public void testNothingAsParameterType() throws Exception {
runTest("compiler/testData/codegen/box/valueClasses/nothingAsParameterType.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
}
@Test
@TestMetadata("overrideFunctionWithDefaultParameter.kt")
public void testOverrideFunctionWithDefaultParameter() throws Exception {
@@ -52095,6 +52095,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
runTest("compiler/testData/codegen/box/valueClasses/mutableSharedMfvcVar.kt");
}
@Test
@TestMetadata("nothingAsParameterType.kt")
public void testNothingAsParameterType() throws Exception {
runTest("compiler/testData/codegen/box/valueClasses/nothingAsParameterType.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
}
@Test
@TestMetadata("overrideFunctionWithDefaultParameter.kt")
public void testOverrideFunctionWithDefaultParameter() throws Exception {
@@ -40165,23 +40165,9 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
private void runTest(String testDataFilePath, java.util.function.Function<String, String> transformer) throws Exception {
KotlinTestUtils.runTest(path -> doTestWithTransformer(path, transformer), TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("overrideFunctionWithDefaultParameter.kt")
public void testOverrideFunctionWithDefaultParameter() throws Exception {
runTest("compiler/testData/codegen/box/valueClasses/overrideFunctionWithDefaultParameter.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
}
@TestMetadata("overrideFunctionWithDefaultParameterGeneric.kt")
public void testOverrideFunctionWithDefaultParameterGeneric() throws Exception {
runTest("compiler/testData/codegen/box/valueClasses/overrideFunctionWithDefaultParameterGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
}
}
@TestMetadata("compiler/testData/codegen/box/vararg")