[IR] Unify MFVC bridge redirection, fix related bugs, support MFVC overriding functions with default parameters
#KT-1179
This commit is contained in:
committed by
Space Team
parent
384ed9cc9e
commit
bf5fa61ffb
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+85
-64
@@ -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.
|
||||
|
||||
+2
-1
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
+12
-21
@@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -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
|
||||
|
||||
+28
-110
@@ -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)
|
||||
}
|
||||
|
||||
+21
-59
@@ -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
|
||||
|
||||
+60
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+52
-121
@@ -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}" }
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+6
-1
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -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
|
||||
}
|
||||
|
||||
|
||||
+114
-2
@@ -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.
|
||||
*
|
||||
|
||||
+4
-2
@@ -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"
|
||||
}
|
||||
+1
-3
@@ -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 {
|
||||
|
||||
+1
-3
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
-12
@@ -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
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
-14
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user