From 51e76aa19a30d99348e80b9fca1e41ba12c97218 Mon Sep 17 00:00:00 2001 From: "Evgeniy.Zhelenskiy" Date: Tue, 11 Oct 2022 16:57:22 +0200 Subject: [PATCH] [IR] Support default arguments Signed-off-by: Evgeniy.Zhelenskiy #KT-1179 --- .../FirBlackBoxCodegenTestGenerated.java | 6 ++ .../lower/JvmMultiFieldValueClassLowering.kt | 87 +++++++++++----- .../lower/JvmValueClassAbstractLowering.kt | 21 +++- ...emoizedMultiFieldValueClassReplacements.kt | 36 ++++--- .../box/valueClasses/defaultParameters.kt | 91 +++++++++++++++++ .../box/valueClasses/defaultParameters.txt | 99 +++++++++++++++++++ .../IrBlackBoxCodegenTestGenerated.java | 6 ++ 7 files changed, 305 insertions(+), 41 deletions(-) create mode 100644 compiler/testData/codegen/box/valueClasses/defaultParameters.kt create mode 100644 compiler/testData/codegen/box/valueClasses/defaultParameters.txt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 44923a6ab5e..9a1d21e4b31 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -50441,6 +50441,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/valueClasses/conditionalExpressions.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); } + @Test + @TestMetadata("defaultParameters.kt") + public void testDefaultParameters() throws Exception { + runTest("compiler/testData/codegen/box/valueClasses/defaultParameters.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); + } + @Test @TestMetadata("equality.kt") public void testEquality() throws Exception { diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt index f94de960a28..b966923d27d 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt @@ -606,18 +606,50 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV .zipWithNext { start: Int, finish: Int -> replacement.explicitParameters.slice(start until finish) } ) for (i in old2newList.indices) { - val (param, newParamList) = old2newList[i] + val (oldParameter, newParamList) = old2newList[i] when (val structure = parametersStructure[i]) { + is RegularMapping -> valueDeclarationsRemapper.registerReplacement(oldParameter, newParamList.single()) is MultiFieldValueClassMapping -> { val mfvcNodeInstance = structure.rootMfvcNode.createInstanceFromValueDeclarationsAndBoxType( structure.boxedType, newParamList ) - valueDeclarationsRemapper.registerReplacement(param, mfvcNodeInstance) + valueDeclarationsRemapper.registerReplacement(oldParameter, mfvcNodeInstance) } - - is RegularMapping -> valueDeclarationsRemapper.registerReplacement(param, newParamList.single()) } } + + withinScope(replacement) { + addDefaultArgumentsIfNeeded(replacement, old2newList, parametersStructure) + } + } + + private fun addDefaultArgumentsIfNeeded( + replacement: IrFunction, + old2newList: List>>, + parametersStructure: List + ) { + for (i in old2newList.indices) { + val (param, newParamList) = old2newList[i] + val defaultValue = replacements.oldMfvcDefaultArguments[param] ?: continue + val structure = parametersStructure[i] + if (structure is MultiFieldValueClassMapping) { + newParamList[0].defaultValue = with(context.createJvmIrBuilder(replacement.symbol)) { + irExprBody(irBlock { + val mfvcNodeInstance = structure.rootMfvcNode.createInstanceFromValueDeclarationsAndBoxType( + param.type as IrSimpleType, newParamList + ) + flattenExpressionTo(defaultValue, mfvcNodeInstance) + +irGet(newParamList[0]) + }) + } + } + } + } + + override fun visitParameter(parameter: IrValueParameter) { + if (parameter.origin != IrDeclarationOrigin.GENERATED_MULTI_FIELD_VALUE_CLASS_PARAMETER) { + super.visitParameter(parameter) + } } fun RootMfvcNode.replacePrimaryMultiFieldValueClassConstructor() { @@ -1033,12 +1065,14 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV if (constructor.isPrimary && constructor.constructedClass.isMultiFieldValueClass && constructor.origin != JvmLoweredDeclarationOrigin.STATIC_MULTI_FIELD_VALUE_CLASS_CONSTRUCTOR ) { - val oldArguments = List(expression.valueArgumentsCount) { expression.getValueArgument(it) } + val oldArguments = List(expression.valueArgumentsCount) { + expression.getValueArgument(it) ?: error("Default arguments for MFVC primary constructors are not yet supported") + } require(rootNode.subnodes.size == oldArguments.size) { "Old ${constructor.render()} must have ${rootNode.subnodes.size} arguments but got ${oldArguments.size}" } for ((subnode, argument) in rootNode.subnodes zip oldArguments) { - argument?.let { flattenExpressionTo(it, instance[subnode.name]!!) } + flattenExpressionTo(argument, instance[subnode.name]!!) } +irCall(rootNode.primaryConstructorImpl).apply { copyTypeArgumentsFrom(expression) @@ -1143,18 +1177,26 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV } private sealed class BlockOrBody { - data class Body(val body: IrBody) : BlockOrBody() - data class Block(val block: IrBlock) : BlockOrBody() + abstract val element: IrElement + + data class Body(val body: IrBody) : BlockOrBody() { + override val element get() = body + } + + data class Block(val block: IrBlock) : BlockOrBody() { + override val element get() = block + } } /** * Finds the most narrow block or body which contains all usages of each of the given variables */ -private fun findNearestBlocksForVariables(variables: Set, body: IrBody): Map { +private fun findNearestBlocksForVariables(variables: Set, body: BlockOrBody): Map { + if (variables.isEmpty()) return mapOf() val variableUsages = mutableMapOf>() val childrenBlocks = mutableMapOf>() - body.acceptVoid(object : IrElementVisitorVoid { + body.element.acceptVoid(object : IrElementVisitorVoid { private val stack = mutableListOf() override fun visitElement(element: IrElement) { element.acceptChildren(this, null) @@ -1168,7 +1210,7 @@ private fun findNearestBlocksForVariables(variables: Set, body: IrBo } override fun visitBlock(expression: IrBlock) { - childrenBlocks.getOrPut(currentStackElement()!!) { mutableListOf() }.add(Block(expression)) + currentStackElement()?.let { childrenBlocks.getOrPut(it) { mutableListOf() }.add(Block(expression)) } stack.add(Block(expression)) super.visitBlock(expression) require(stack.removeLast() == Block(expression)) { "Invalid stack" } @@ -1195,7 +1237,7 @@ private fun findNearestBlocksForVariables(variables: Set, body: IrBo } } - return variables.associateWith { dfs(BlockOrBody.Body(body), it) } + return variables.associateWith { dfs(body, it) } } private fun IrStatement.containsUsagesOf(variablesSet: Set): Boolean { @@ -1217,20 +1259,20 @@ private fun IrStatement.containsUsagesOf(variablesSet: Set): Boolean return used } +private fun IrBody.makeBodyWithAddedVariables(context: JvmBackendContext, variables: Set, symbol: IrSymbol) = + BlockOrBody.Body(this).makeBodyWithAddedVariables(context, variables, symbol) as IrBody + /** * Adds declarations of the variables to the most narrow possible block or body. * It adds them before the first usage within the block and inlines initialization of them when possible. */ -fun IrBody.makeBodyWithAddedVariables( - context: JvmBackendContext, - variables: Set, - symbol: IrSymbol -): IrBody { +private fun BlockOrBody.makeBodyWithAddedVariables(context: JvmBackendContext, variables: Set, symbol: IrSymbol): IrElement { + if (variables.isEmpty()) return element val nearestBlocks = findNearestBlocksForVariables(variables, this) val containingVariables: Map> = nearestBlocks.entries .mapNotNull { (k, v) -> if (v != null) k to v else null } .groupBy({ (_, v) -> v }, { (k, _) -> k }) - return transform(object : IrElementTransformerVoid() { + return element.transform(object : IrElementTransformerVoid() { private fun getFlattenedStatements(container: IrStatementContainer): Sequence = sequence { for (statement in container.statements) { if (statement is IrStatementContainer) { @@ -1306,12 +1348,11 @@ fun IrBody.makeBodyWithAddedVariables( override fun visitExpressionBody(body: IrExpressionBody): IrBody { val lowering = this containingVariables[BlockOrBody.Body(body)]?.takeIf { it.isNotEmpty() }?.let { bodyVars -> - val blockBody = context.createJvmIrBuilder(symbol).irBlockBody { - +irReturn(body.expression.transform(lowering, null)) + return with(context.createJvmIrBuilder(symbol)) { + val blockBody = irBlock { +body.expression.transform(lowering, null) } + replaceSetVariableWithInitialization(bodyVars, blockBody) + irExprBody(blockBody) } - blockBody.transformChildrenVoid() - replaceSetVariableWithInitialization(bodyVars, blockBody) - return blockBody } return super.visitExpressionBody(body) } diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmValueClassAbstractLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmValueClassAbstractLowering.kt index 4d86ba4014c..8fcf51470a9 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmValueClassAbstractLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmValueClassAbstractLowering.kt @@ -89,7 +89,7 @@ internal abstract class JvmValueClassAbstractLowering(val context: JvmBackendCon private fun transformFlattenedConstructor(function: IrConstructor, replacement: IrConstructor): List? { replacement.valueParameters.forEach { - it.transformChildrenVoid() + visitParameter(it) it.defaultValue?.patchDeclarationParents(replacement) } allScopes.push(createScope(function)) @@ -106,9 +106,18 @@ internal abstract class JvmValueClassAbstractLowering(val context: JvmBackendCon protected abstract fun transformSecondaryConstructorFlat(constructor: IrConstructor, replacement: IrSimpleFunction): List + open fun visitParameter(parameter: IrValueParameter) { + parameter.transformChildrenVoid() + } + + final override fun visitValueParameterNew(declaration: IrValueParameter): IrStatement { + visitParameter(declaration) + return declaration + } + private fun transformSimpleFunctionFlat(function: IrSimpleFunction, replacement: IrSimpleFunction): List { replacement.valueParameters.forEach { - it.transformChildrenVoid() + visitParameter(it) it.defaultValue?.patchDeclarationParents(replacement) } allScopes.push(createScope(replacement)) @@ -184,7 +193,11 @@ internal abstract class JvmValueClassAbstractLowering(val context: JvmBackendCon function, replacement, when { - function.isTypedEquals() -> InlineClassAbi.mangledNameFor(function, mangleReturnTypes = false, useOldMangleRules = false) + function.isValueClassTypedEquals -> InlineClassAbi.mangledNameFor( + function, + mangleReturnTypes = false, + useOldMangleRules = false + ) // If the original function has signature which need mangling we still need to replace it with a mangled version. (!function.isFakeOverride || function.findInterfaceImplementation(context.state.jvmDefaultMode) != null) && when (specificMangle) { SpecificMangle.Inline -> function.signatureRequiresMangling(includeInline = true, includeMFVC = false) @@ -233,4 +246,4 @@ internal abstract class JvmValueClassAbstractLowering(val context: JvmBackendCon abstract fun createBridgeDeclaration(source: IrSimpleFunction, replacement: IrSimpleFunction, mangledName: Name): IrSimpleFunction protected abstract fun createBridgeBody(source: IrSimpleFunction, target: IrSimpleFunction, original: IrFunction, inverted: Boolean) -} \ No newline at end of file +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt index 08950704183..36cbf6953c0 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt @@ -6,14 +6,14 @@ package org.jetbrains.kotlin.backend.jvm import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.MultiFieldValueClassMapping -import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound -import org.jetbrains.kotlin.backend.jvm.ir.extensionReceiverName -import org.jetbrains.kotlin.backend.jvm.ir.findSuperDeclaration -import org.jetbrains.kotlin.backend.jvm.ir.isStaticValueClassReplacement +import org.jetbrains.kotlin.backend.jvm.ir.* import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor +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.IrExpression import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.IrSimpleType @@ -44,29 +44,34 @@ class MemoizedMultiFieldValueClassReplacements( targetFunction: IrFunction, originWhenFlattened: IrDeclarationOrigin, ): RemappedParameter { + val oldParam = this if (!type.needsMfvcFlattening()) return RemappedParameter.RegularMapping( targetFunction.addValueParameter { - updateFrom(this@grouped) - this.name = this@grouped.name + updateFrom(oldParam) + this.name = oldParam.name index = targetFunction.valueParameters.size }.apply { - copyAnnotationsFrom(this@grouped) + defaultValue = oldParam.defaultValue + copyAnnotationsFrom(oldParam) } ) - val rootMfvcNode = this@MemoizedMultiFieldValueClassReplacements.getRootMfvcNode(type.erasedUpperBound)!! - require(!hasDefaultValue()) { "Default parameters values are not supported for multi-field value classes" } + val rootMfvcNode = this@MemoizedMultiFieldValueClassReplacements.getRootMfvcNode(type.erasedUpperBound) + defaultValue?.expression?.let { oldMfvcDefaultArguments.putIfAbsent(this, it) } val newType = type.substitute(substitutionMap) as IrSimpleType val localSubstitutionMap = makeTypeArgumentsFromType(newType) val valueParameters = rootMfvcNode.mapLeaves { leaf -> targetFunction.addValueParameter { - updateFrom(this@grouped) - this.name = Name.identifier("${name ?: this@grouped.name}-${leaf.fullFieldName}") + updateFrom(oldParam) + this.name = Name.identifier("${name ?: oldParam.name}-${leaf.fullFieldName}") type = leaf.type.substitute(localSubstitutionMap) origin = originWhenFlattened index = targetFunction.valueParameters.size - }.apply { - defaultValue = null - copyAnnotationsFrom(this@grouped) + isAssignable = isAssignable || oldParam.defaultValue != null + }.also { newParam -> + newParam.defaultValue = oldParam.defaultValue?.let { + context.createJvmIrBuilder(targetFunction.symbol).run { irExprBody(irGet(newParam)) } + } + require(oldParam.annotations.isEmpty()) { "Annotations are not supported for MFVC parameters" } } } return MultiFieldValueClassMapping(rootMfvcNode, newType, valueParameters) @@ -79,6 +84,9 @@ class MemoizedMultiFieldValueClassReplacements( originWhenFlattened: IrDeclarationOrigin, ): List = map { it.grouped(name, substitutionMap, targetFunction, originWhenFlattened) } + + val oldMfvcDefaultArguments = ConcurrentHashMap() + private fun buildReplacement( function: IrFunction, replacementOrigin: IrDeclarationOrigin, diff --git a/compiler/testData/codegen/box/valueClasses/defaultParameters.kt b/compiler/testData/codegen/box/valueClasses/defaultParameters.kt new file mode 100644 index 00000000000..8acc749a6b5 --- /dev/null +++ b/compiler/testData/codegen/box/valueClasses/defaultParameters.kt @@ -0,0 +1,91 @@ +// CHECK_BYTECODE_LISTING +// WITH_STDLIB +// TARGET_BACKEND: JVM_IR +// WORKS_WHEN_VALUE_CLASS +// LANGUAGE: +ValueClasses + +@JvmInline +value class DPoint(/*inline */val x: Double/* = 1.0*/, /*inline */val y: Double/* = 2.0*/) { + fun f1(a: Int, b: Int = -1, c: DPoint = DPoint(-2.0, -3.0)) = listOf(this, x, y, a, b, c) +} + +@JvmInline +value class DSegment(/*inline */val p1: DPoint/* = DPoint(3.0, 4.0)*/, /*inline */val p2: DPoint/* = DPoint(5.0, 6.0)*/, /*inline */val n: Int/* = 7*/) { + fun f2(a: Int, b: Int = -1, c: DPoint = DPoint(-2.0, -3.0)) = listOf(this, p1, p2, n, a, b, c) +} + +data class Wrapper(val segment: DSegment = DSegment(DPoint(8.0, 9.0), DPoint(10.0, 11.0), 7), val n: Int = 12) { + fun f3(a: Int, b: Int = -1, c: DPoint = DPoint(-2.0, -3.0)) = listOf(this, segment, n, a, b, c) +} + +fun complexFun(a1: Double, a2: DPoint, a3: Double = a1 * a2.x * a2.y, a4: DPoint = DPoint(a2.x * a1 * a3, a2.y * a1 * a3)) = "$a1, $a2, $a3, $a4" + +inline fun complexInlineFun(a1: Double, a2: DPoint, a3: Double = a1 * a2.x * a2.y, a4: DPoint = DPoint(a2.x * a1 * a3, a2.y * a1 * a3)) = "$a1, $a2, $a3, $a4" + +fun box(): String { +// comments bellow are because MFVC primary constructors default parameters require support of inline arguments in regular functions +// require(DPoint() == DPoint(1.0, 2.0)) { "${DPoint()} ${DPoint(1.0, 2.0)}" } +// require(DPoint(3.0) == DPoint(3.0, 2.0)) { "${DPoint()} ${DPoint(3.0, 2.0)}" } +// require(DPoint(x = 3.0) == DPoint(3.0, 2.0)) { "${DPoint()} ${DPoint(3.0, 2.0)}" } +// require(DPoint(y = 3.0) == DPoint(1.0, 3.0)) { "${DPoint()} ${DPoint(1.0, 3.0)}" } +// val defaultDPoint = DPoint() + val defaultDPoint = DPoint(1.0, 2.0) + require(defaultDPoint.f1(4) == listOf(DPoint(1.0, 2.0), 1.0, 2.0, 4, -1, DPoint(-2.0, -3.0))) { + defaultDPoint.f1(4).toString() + } + require(defaultDPoint.f1(4, 1, DPoint(2.0, 3.0)) == listOf(DPoint(1.0, 2.0), 1.0, 2.0, 4, 1, DPoint(2.0, 3.0))) { + defaultDPoint.f1(4, 1, DPoint(2.0, 3.0)).toString() + } + require(DPoint(-1.0, -2.0).f1(4) == listOf(DPoint(-1.0, -2.0), -1.0, -2.0, 4, -1, DPoint(-2.0, -3.0))) { + defaultDPoint.f1(4).toString() + } + require(DPoint(-1.0, -2.0).f1(4, 1, DPoint(2.0, 3.0)) == listOf(DPoint(-1.0, -2.0), -1.0, -2.0, 4, 1, DPoint(2.0, 3.0))) { + defaultDPoint.f1(4, 1, DPoint(2.0, 3.0)).toString() + } + +// require(DSegment() == DSegment(DPoint(3.0, 4.0), DPoint(5.0, 6.0), 7)) { DSegment().toString() } +// val defaultDSegment = DSegment() + val defaultDSegment = DSegment(DPoint(3.0, 4.0), DPoint(5.0, 6.0), 7) + require(defaultDSegment.f2(100) == listOf(defaultDSegment, DPoint(3.0, 4.0), DPoint(5.0, 6.0), 7, 100, -1, DPoint(-2.0, -3.0))) { + defaultDSegment.f2(100).toString() + } + require(defaultDSegment.f2(100, b = 1) == listOf(defaultDSegment, DPoint(3.0, 4.0), DPoint(5.0, 6.0), 7, 100, 1, DPoint(-2.0, -3.0))) { + defaultDSegment.f2(100, b = 1).toString() + } + + require(Wrapper() == Wrapper(DSegment(DPoint(8.0, 9.0), DPoint(10.0, 11.0), 7), 12)) { Wrapper().toString() } + require(Wrapper().f3(100) == listOf(Wrapper(), DSegment(DPoint(8.0, 9.0), DPoint(10.0, 11.0), 7), 12, 100, -1, DPoint(-2.0, -3.0))) { + Wrapper().f3(100).toString() + } + require(Wrapper().f3(100, b = 1) == listOf(Wrapper(), DSegment(DPoint(8.0, 9.0), DPoint(10.0, 11.0), 7), 12, 100, 1, DPoint(-2.0, -3.0))) { + Wrapper().f3(100, b = 1).toString() + } + + require(complexFun(2.0, DPoint(3.0, 5.0)) == "2.0, ${DPoint(3.0, 5.0)}, 30.0, ${DPoint(180.0, 300.0)}") { + complexFun(2.0, DPoint(3.0, 5.0)) + } + require(complexFun(2.0, DPoint(3.0, 5.0), 7.0) == "2.0, ${DPoint(3.0, 5.0)}, 7.0, ${DPoint(42.0, 70.0)}") { + complexFun(2.0, DPoint(3.0, 5.0), 7.0) + } + require(complexFun(2.0, DPoint(3.0, 5.0), a4 = DPoint(11.0, 13.0)) == "2.0, ${DPoint(3.0, 5.0)}, 30.0, ${DPoint(11.0, 13.0)}") { + complexFun(2.0, DPoint(3.0, 5.0), a4 = DPoint(11.0, 13.0)) + } + require(complexFun(2.0, DPoint(3.0, 5.0), 7.0, DPoint(11.0, 13.0)) == "2.0, ${DPoint(3.0, 5.0)}, 7.0, ${DPoint(11.0, 13.0)}") { + complexFun(2.0, DPoint(3.0, 5.0), 7.0, DPoint(11.0, 13.0)) + } + + require(complexInlineFun(2.0, DPoint(3.0, 5.0)) == "2.0, ${DPoint(3.0, 5.0)}, 30.0, ${DPoint(180.0, 300.0)}") { + complexInlineFun(2.0, DPoint(3.0, 5.0)) + } + require(complexInlineFun(2.0, DPoint(3.0, 5.0), 7.0) == "2.0, ${DPoint(3.0, 5.0)}, 7.0, ${DPoint(42.0, 70.0)}") { + complexInlineFun(2.0, DPoint(3.0, 5.0), 7.0) + } + require(complexInlineFun(2.0, DPoint(3.0, 5.0), a4 = DPoint(11.0, 13.0)) == "2.0, ${DPoint(3.0, 5.0)}, 30.0, ${DPoint(11.0, 13.0)}") { + complexInlineFun(2.0, DPoint(3.0, 5.0), a4 = DPoint(11.0, 13.0)) + } + require(complexInlineFun(2.0, DPoint(3.0, 5.0), 7.0, DPoint(11.0, 13.0)) == "2.0, ${DPoint(3.0, 5.0)}, 7.0, ${DPoint(11.0, 13.0)}") { + complexInlineFun(2.0, DPoint(3.0, 5.0), 7.0, DPoint(11.0, 13.0)) + } + + return "OK" +} diff --git a/compiler/testData/codegen/box/valueClasses/defaultParameters.txt b/compiler/testData/codegen/box/valueClasses/defaultParameters.txt new file mode 100644 index 00000000000..58bbe083dcb --- /dev/null +++ b/compiler/testData/codegen/box/valueClasses/defaultParameters.txt @@ -0,0 +1,99 @@ +@kotlin.jvm.JvmInline +@kotlin.Metadata +public final class DPoint { + // source: 'defaultParameters.kt' + private final field x: double + private final field y: double + private synthetic method (p0: double, p1: double): void + public synthetic final static method box-impl(p0: double, p1: double): DPoint + public final static method constructor-impl(p0: double, p1: double): void + public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean + public static method equals-impl(p0: double, p1: double, p2: java.lang.Object): boolean + public final static method equals-impl0(p0: double, p1: double, p2: double, p3: double): boolean + public synthetic static method f1-lIoT8es$default(p0: double, p1: double, p2: int, p3: int, p4: double, p5: double, p6: int, p7: java.lang.Object): java.util.List + public final static @org.jetbrains.annotations.NotNull method f1-lIoT8es(p0: double, p1: double, p2: int, p3: int, p4: double, p5: double): java.util.List + public final method getX(): double + public final method getY(): double + public method hashCode(): int + public static method hashCode-impl(p0: double, p1: double): int + 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-x(): double + public synthetic final method unbox-impl-y(): double +} + +@kotlin.jvm.JvmInline +@kotlin.Metadata +public final class DSegment { + // source: 'defaultParameters.kt' + private final field n: int + private final field p1-x: double + private final field p1-y: double + private final field p2-x: double + private final field p2-y: double + private synthetic method (p0: double, p1: double, p2: double, p3: double, p4: int): void + public synthetic final static method box-impl(p0: double, p1: double, p2: double, p3: double, p4: int): DSegment + public final static method constructor-impl(p0: double, p1: double, p2: double, p3: double, p4: int): void + public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean + public static method equals-impl(p0: double, p1: double, p2: double, p3: double, p4: int, p5: java.lang.Object): boolean + public final static method equals-impl0(p0: double, p1: double, p2: double, p3: double, p4: int, p5: double, p6: double, p7: double, p8: double, p9: int): boolean + public synthetic static method f2-lIoT8es$default(p0: double, p1: double, p2: double, p3: double, p4: int, p5: int, p6: int, p7: double, p8: double, p9: int, p10: java.lang.Object): java.util.List + public final static @org.jetbrains.annotations.NotNull method f2-lIoT8es(p0: double, p1: double, p2: double, p3: double, p4: int, p5: int, p6: int, p7: double, p8: double): java.util.List + public final method getN(): int + public final @org.jetbrains.annotations.NotNull method getP1(): DPoint + public final @org.jetbrains.annotations.NotNull method getP2(): DPoint + public method hashCode(): int + public static method hashCode-impl(p0: double, p1: double, p2: double, p3: double, p4: int): int + public @org.jetbrains.annotations.NotNull method toString(): java.lang.String + public static method toString-impl(p0: double, p1: double, p2: double, p3: double, p4: int): java.lang.String + public synthetic final method unbox-impl-n(): int + public synthetic final method unbox-impl-p1(): DPoint + public synthetic final method unbox-impl-p1-x(): double + public synthetic final method unbox-impl-p1-y(): double + public synthetic final method unbox-impl-p2(): DPoint + public synthetic final method unbox-impl-p2-x(): double + public synthetic final method unbox-impl-p2-y(): double +} + +@kotlin.Metadata +public final class DefaultParametersKt { + // source: 'defaultParameters.kt' + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public synthetic static method complexFun-552ch2I$default(p0: double, p1: double, p2: double, p3: double, p4: double, p5: double, p6: int, p7: java.lang.Object): java.lang.String + public final static @org.jetbrains.annotations.NotNull method complexFun-552ch2I(p0: double, p1: double, p2: double, p3: double, p4: double, p5: double): java.lang.String + public synthetic static method complexInlineFun-552ch2I$default(p0: double, p1: double, p2: double, p3: double, p4: double, p5: double, p6: int, p7: java.lang.Object): java.lang.String + public final static @org.jetbrains.annotations.NotNull method complexInlineFun-552ch2I(p0: double, p1: double, p2: double, p3: double, p4: double, p5: double): java.lang.String + public final inner class kotlin/jvm/internal/Ref$DoubleRef +} + +@kotlin.Metadata +public final class Wrapper { + // source: 'defaultParameters.kt' + private final field n: int + private final field segment-n: int + private final field segment-p1-x: double + private final field segment-p1-y: double + private final field segment-p2-x: double + private final field segment-p2-y: double + public method (): void + public method (p0: double, p1: double, p2: double, p3: double, p4: int, p5: int): void + public synthetic method (p0: double, p1: double, p2: double, p3: double, p4: int, p5: int, p6: int, p7: kotlin.jvm.internal.DefaultConstructorMarker): void + public final @org.jetbrains.annotations.NotNull method component1(): DSegment + public final method component2(): int + public synthetic static method copy-GPBa7dw$default(p0: Wrapper, p1: double, p2: double, p3: double, p4: double, p5: int, p6: int, p7: int, p8: java.lang.Object): Wrapper + public final @org.jetbrains.annotations.NotNull method copy-GPBa7dw(p0: double, p1: double, p2: double, p3: double, p4: int, p5: int): Wrapper + public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean + public synthetic static method f3-lIoT8es$default(p0: Wrapper, p1: int, p2: int, p3: double, p4: double, p5: int, p6: java.lang.Object): java.util.List + public final @org.jetbrains.annotations.NotNull method f3-lIoT8es(p0: int, p1: int, p2: double, p3: double): java.util.List + public final method getN(): int + public final @org.jetbrains.annotations.NotNull method getSegment(): DSegment + public synthetic final method getSegment-n(): int + public synthetic final method getSegment-p1(): DPoint + public synthetic final method getSegment-p1-x(): double + public synthetic final method getSegment-p1-y(): double + public synthetic final method getSegment-p2(): DPoint + public synthetic final method getSegment-p2-x(): double + public synthetic final method getSegment-p2-y(): double + public method hashCode(): int + public @org.jetbrains.annotations.NotNull method toString(): java.lang.String +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 06b7794f4f3..af14d91dc25 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -50441,6 +50441,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/valueClasses/conditionalExpressions.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); } + @Test + @TestMetadata("defaultParameters.kt") + public void testDefaultParameters() throws Exception { + runTest("compiler/testData/codegen/box/valueClasses/defaultParameters.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); + } + @Test @TestMetadata("equality.kt") public void testEquality() throws Exception {