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 7b8959f8e50..030d9c8d145 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 @@ -25182,6 +25182,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT public void testTypeAlias() throws Exception { runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt"); } + + @Test + @TestMetadata("withTypeParameter.kt") + public void testWithTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt"); + } } @Nested diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/ExpectDeclarationRemover.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/ExpectDeclarationRemover.kt index 0e1c577ee24..b4b8ac3957b 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/ExpectDeclarationRemover.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/ExpectDeclarationRemover.kt @@ -26,6 +26,8 @@ import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver // `doRemove` means should expect-declaration be removed from IR @OptIn(ObsoleteDescriptorBasedAPI::class) class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private val doRemove: Boolean) : IrElementVisitorVoid { + private val typeParameterSubstitutionMap = mutableMapOf, Map>() + override fun visitElement(element: IrElement) { element.acceptChildrenVoid(this) } @@ -97,13 +99,29 @@ class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private va // the `actual fun` or `actual constructor` for this may be in a different module. // Nothing we can do with those. // TODO they may not actually have the defaults though -- may be a frontend bug. - val expectParameter = function.findExpectForActual()?.valueParameters?.get(index) ?: return + val expectFunction = function.findExpectForActual() + val expectParameter = expectFunction?.valueParameters?.get(index) ?: return val defaultValue = expectParameter.defaultValue ?: return + val expectToActual = expectFunction to function + if (expectToActual !in typeParameterSubstitutionMap) { + val functionTypeParameters = collectTypeParameters(function) + val expectFunctionTypeParameters = collectTypeParameters(expectFunction) + + expectFunctionTypeParameters.zip(functionTypeParameters).let { typeParametersMapping -> + typeParameterSubstitutionMap[expectToActual] = typeParametersMapping.toMap() + } + } + defaultValue.let { originalDefault -> declaration.defaultValue = declaration.factory.createExpressionBody(originalDefault.startOffset, originalDefault.endOffset) { - expression = originalDefault.expression.deepCopyWithSymbols(function).remapExpectValueSymbols() + expression = originalDefault.expression + .deepCopyWithSymbols(function) + .remapExpectValueSymbols() + .apply { + remapTypes(IrTypeParameterRemapper(typeParameterSubstitutionMap.getValue(expectToActual))) + } } } } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt index c6781ef62db..430da47731d 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt @@ -345,19 +345,6 @@ class InlineClassLowering(val context: CommonBackendContext) { } } - private fun collectTypeParameters(declaration: IrTypeParametersContainer): List { - val result = mutableListOf() - - fun collectImpl(declaration: IrDeclaration) { - if (declaration is IrTypeParametersContainer) result.addAll(declaration.typeParameters) - if (declaration is IrClass && declaration.isInner) collectImpl(declaration.parent as IrDeclaration) - } - - collectImpl(declaration) - - return result - } - private fun createStaticBodilessMethod(function: IrFunction): IrSimpleFunction = context.irFactory.createStaticFunctionWithReceivers( function.parent, diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt index 652fcada961..031533cab8f 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt @@ -602,4 +602,20 @@ internal fun IrConst.shallowCopy() = IrConstImpl( type, kind, value -) \ No newline at end of file +) + +fun collectTypeParameters(declaration: IrTypeParametersContainer): List { + val result = mutableListOf() + + fun collectImpl(declaration: IrDeclaration) { + if (declaration is IrTypeParametersContainer) { + result.addAll(declaration.typeParameters) + declaration.parentClassOrNull?.let { collectImpl(it) } + } + if (declaration is IrClass && declaration.isInner) collectImpl(declaration.parent as IrDeclaration) + } + + collectImpl(declaration) + + return result +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt b/compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt new file mode 100644 index 00000000000..4c4444cb2f9 --- /dev/null +++ b/compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt @@ -0,0 +1,59 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: lib +// FILE: common.kt + +expect fun topLevel(a: T, b: (T) -> Int = { 1 }): String + +actual fun topLevel(a: T, b: (T) -> Int): String = b(a).toString() + +expect class Foo() { + fun member(a: T, b: (T) -> Int = { 2 }): String +} + +actual class Foo actual constructor() { + actual fun member(a: T, b: (T) -> Int): String = b(a).toString() +} + +expect class Bar() { + fun member(a: T, b: (T) -> Int = { 3 }): String +} + +actual class Bar actual constructor() { + actual fun member(a: T, b: (T) -> Int): String = b(a).toString() +} + +expect class A { + inner class B { + fun foo(t: T, n: N, h: H, a: (T, N, H) -> Int = { _, _, _ -> 4 }): String + } +} + +actual class A { + actual inner class B { + actual fun foo(t: T, n: N, h: H, a: (T, N, H) -> Int) = a(t, n, h).toString() + } +} + +// MODULE: main(lib) +// FILE: main.kt + +import kotlin.test.assertEquals + +fun box(): String { + assertEquals("1", topLevel("OK")) + assertEquals("73", topLevel("OK") { 73 }) + + val foo = Foo() + assertEquals("2", foo.member("OK")) + assertEquals("42", foo.member("OK") { 42 }) + + val bar = Bar() + assertEquals("3", bar.member("OK")) + assertEquals("37", bar.member("OK") { 37 }) + + val b = A().B() + assertEquals("4", b.foo(1, 2.0, 3)) + assertEquals("6", b.foo(1, 2.0, 3) { t, n, h -> t + n.toInt() + h }) + + return "OK" +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 6db0c4f597d..f72628d0f52 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -25164,6 +25164,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testTypeAlias() throws Exception { runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt"); } + + @Test + @TestMetadata("withTypeParameter.kt") + public void testWithTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt"); + } } @Nested 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 2ec7e9bc64c..01d28c8be04 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 @@ -25182,6 +25182,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes public void testTypeAlias() throws Exception { runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt"); } + + @Test + @TestMetadata("withTypeParameter.kt") + public void testWithTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt"); + } } @Nested diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index c3bee5eedd9..46cb6d75219 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -21301,6 +21301,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes public void testTypeAlias() throws Exception { runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt"); } + + @TestMetadata("withTypeParameter.kt") + public void testWithTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt"); + } } @TestMetadata("compiler/testData/codegen/box/multiplatform/exhaustiveness") diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 4e76d2a64c8..04a9585549c 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -16745,6 +16745,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes public void testTypeAlias() throws Exception { runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt"); } + + @TestMetadata("withTypeParameter.kt") + public void testWithTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt"); + } } @TestMetadata("compiler/testData/codegen/box/multiplatform/exhaustiveness") diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 6c25c6e735e..72b0968fdbf 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -16166,6 +16166,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { public void testTypeAlias() throws Exception { runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt"); } + + @TestMetadata("withTypeParameter.kt") + public void testWithTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt"); + } } @TestMetadata("compiler/testData/codegen/box/multiplatform/exhaustiveness") diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index bd19e2a3497..a957b09e334 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -16231,6 +16231,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { public void testTypeAlias() throws Exception { runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt"); } + + @TestMetadata("withTypeParameter.kt") + public void testWithTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt"); + } } @TestMetadata("compiler/testData/codegen/box/multiplatform/exhaustiveness") diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index 2fd707cdb8a..e0111b332da 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -9977,6 +9977,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest public void testTypeAlias() throws Exception { runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt"); } + + @TestMetadata("withTypeParameter.kt") + public void testWithTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt"); + } } @TestMetadata("compiler/testData/codegen/box/multiplatform/exhaustiveness")