From b0367d93991b5cf93d266e395c312eaeca774d36 Mon Sep 17 00:00:00 2001 From: "Evgeniy.Zhelenskiy" Date: Mon, 29 Jan 2024 04:04:59 +0000 Subject: [PATCH] [Reflection] Support `callBy` for inline class interface functions with default parameters #KT-57972 --- ...LFirBlackBoxCodegenBasedTestGenerated.java | 36 +++++++++++ ...rsedBlackBoxCodegenBasedTestGenerated.java | 36 +++++++++++ ...LightTreeBlackBoxCodegenTestGenerated.java | 36 +++++++++++ ...hIrFakeOverrideGeneratorTestGenerated.java | 36 +++++++++++ .../FirPsiBlackBoxCodegenTestGenerated.java | 36 +++++++++++ ...DefaultParametersFromDifferentFunctions.kt | 60 +++++++++++++++++++ ...ametersFromDifferentFunctionsJvmDefault.kt | 60 +++++++++++++++++++ .../reflection/callBy/inlineClassInterface.kt | 44 ++++++++++++++ .../callBy/inlineClassInterfaceJvmDefault.kt | 45 ++++++++++++++ .../box/reflection/callBy/mfvcInterface.kt | 46 ++++++++++++++ .../callBy/mfvcInterfaceJvmDefault.kt | 46 ++++++++++++++ .../JvmAbiConsistencyTestBoxGenerated.java | 36 +++++++++++ .../IrBlackBoxCodegenTestGenerated.java | 36 +++++++++++ ...kBoxCodegenWithIrInlinerTestGenerated.java | 36 +++++++++++ .../LightAnalysisModeTestGenerated.java | 30 ++++++++++ .../reflect/jvm/internal/KFunctionImpl.kt | 37 ++++++++++-- .../reflect/jvm/internal/KParameterImpl.kt | 12 +++- .../internal/calls/ValueClassAwareCaller.kt | 36 +++++++++-- 18 files changed, 691 insertions(+), 13 deletions(-) create mode 100644 compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctions.kt create mode 100644 compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt create mode 100644 compiler/testData/codegen/box/reflection/callBy/inlineClassInterface.kt create mode 100644 compiler/testData/codegen/box/reflection/callBy/inlineClassInterfaceJvmDefault.kt create mode 100644 compiler/testData/codegen/box/reflection/callBy/mfvcInterface.kt create mode 100644 compiler/testData/codegen/box/reflection/callBy/mfvcInterfaceJvmDefault.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirBlackBoxCodegenBasedTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirBlackBoxCodegenBasedTestGenerated.java index 82ca2a487cb..8f635e698f8 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirBlackBoxCodegenBasedTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirBlackBoxCodegenBasedTestGenerated.java @@ -46667,6 +46667,18 @@ public class LLFirBlackBoxCodegenBasedTestGenerated extends AbstractLLFirBlackBo runTest("compiler/testData/codegen/box/reflection/callBy/boundJvmStaticInObject.kt"); } + @Test + @TestMetadata("brokenDefaultParametersFromDifferentFunctions.kt") + public void testBrokenDefaultParametersFromDifferentFunctions() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctions.kt"); + } + + @Test + @TestMetadata("brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt") + public void testBrokenDefaultParametersFromDifferentFunctionsJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt"); + } + @Test @TestMetadata("companionObject.kt") public void testCompanionObject() throws Exception { @@ -46715,6 +46727,18 @@ public class LLFirBlackBoxCodegenBasedTestGenerated extends AbstractLLFirBlackBo runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt"); } + @Test + @TestMetadata("inlineClassInterface.kt") + public void testInlineClassInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterface.kt"); + } + + @Test + @TestMetadata("inlineClassInterfaceJvmDefault.kt") + public void testInlineClassInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterfaceJvmDefault.kt"); + } + @Test @TestMetadata("inlineClassMembers.kt") public void testInlineClassMembers() throws Exception { @@ -46781,6 +46805,18 @@ public class LLFirBlackBoxCodegenBasedTestGenerated extends AbstractLLFirBlackBo runTest("compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt"); } + @Test + @TestMetadata("mfvcInterface.kt") + public void testMfvcInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterface.kt"); + } + + @Test + @TestMetadata("mfvcInterfaceJvmDefault.kt") + public void testMfvcInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterfaceJvmDefault.kt"); + } + @Test @TestMetadata("mfvcKt61304.kt") public void testMfvcKt61304() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirReversedBlackBoxCodegenBasedTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirReversedBlackBoxCodegenBasedTestGenerated.java index d5dac3389b1..7d1f20ca600 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirReversedBlackBoxCodegenBasedTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirReversedBlackBoxCodegenBasedTestGenerated.java @@ -46667,6 +46667,18 @@ public class LLFirReversedBlackBoxCodegenBasedTestGenerated extends AbstractLLFi runTest("compiler/testData/codegen/box/reflection/callBy/boundJvmStaticInObject.kt"); } + @Test + @TestMetadata("brokenDefaultParametersFromDifferentFunctions.kt") + public void testBrokenDefaultParametersFromDifferentFunctions() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctions.kt"); + } + + @Test + @TestMetadata("brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt") + public void testBrokenDefaultParametersFromDifferentFunctionsJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt"); + } + @Test @TestMetadata("companionObject.kt") public void testCompanionObject() throws Exception { @@ -46715,6 +46727,18 @@ public class LLFirReversedBlackBoxCodegenBasedTestGenerated extends AbstractLLFi runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt"); } + @Test + @TestMetadata("inlineClassInterface.kt") + public void testInlineClassInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterface.kt"); + } + + @Test + @TestMetadata("inlineClassInterfaceJvmDefault.kt") + public void testInlineClassInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterfaceJvmDefault.kt"); + } + @Test @TestMetadata("inlineClassMembers.kt") public void testInlineClassMembers() throws Exception { @@ -46781,6 +46805,18 @@ public class LLFirReversedBlackBoxCodegenBasedTestGenerated extends AbstractLLFi runTest("compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt"); } + @Test + @TestMetadata("mfvcInterface.kt") + public void testMfvcInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterface.kt"); + } + + @Test + @TestMetadata("mfvcInterfaceJvmDefault.kt") + public void testMfvcInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterfaceJvmDefault.kt"); + } + @Test @TestMetadata("mfvcKt61304.kt") public void testMfvcKt61304() throws Exception { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java index d78e8f57a89..fffd55c242a 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java @@ -46264,6 +46264,18 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr runTest("compiler/testData/codegen/box/reflection/callBy/boundJvmStaticInObject.kt"); } + @Test + @TestMetadata("brokenDefaultParametersFromDifferentFunctions.kt") + public void testBrokenDefaultParametersFromDifferentFunctions() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctions.kt"); + } + + @Test + @TestMetadata("brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt") + public void testBrokenDefaultParametersFromDifferentFunctionsJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt"); + } + @Test @TestMetadata("companionObject.kt") public void testCompanionObject() throws Exception { @@ -46312,6 +46324,18 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt"); } + @Test + @TestMetadata("inlineClassInterface.kt") + public void testInlineClassInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterface.kt"); + } + + @Test + @TestMetadata("inlineClassInterfaceJvmDefault.kt") + public void testInlineClassInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterfaceJvmDefault.kt"); + } + @Test @TestMetadata("inlineClassMembers.kt") public void testInlineClassMembers() throws Exception { @@ -46378,6 +46402,18 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr runTest("compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt"); } + @Test + @TestMetadata("mfvcInterface.kt") + public void testMfvcInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterface.kt"); + } + + @Test + @TestMetadata("mfvcInterfaceJvmDefault.kt") + public void testMfvcInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterfaceJvmDefault.kt"); + } + @Test @TestMetadata("mfvcKt61304.kt") public void testMfvcKt61304() throws Exception { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated.java index 8cd44da7256..678802f2382 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated.java @@ -46264,6 +46264,18 @@ public class FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated runTest("compiler/testData/codegen/box/reflection/callBy/boundJvmStaticInObject.kt"); } + @Test + @TestMetadata("brokenDefaultParametersFromDifferentFunctions.kt") + public void testBrokenDefaultParametersFromDifferentFunctions() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctions.kt"); + } + + @Test + @TestMetadata("brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt") + public void testBrokenDefaultParametersFromDifferentFunctionsJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt"); + } + @Test @TestMetadata("companionObject.kt") public void testCompanionObject() throws Exception { @@ -46312,6 +46324,18 @@ public class FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt"); } + @Test + @TestMetadata("inlineClassInterface.kt") + public void testInlineClassInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterface.kt"); + } + + @Test + @TestMetadata("inlineClassInterfaceJvmDefault.kt") + public void testInlineClassInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterfaceJvmDefault.kt"); + } + @Test @TestMetadata("inlineClassMembers.kt") public void testInlineClassMembers() throws Exception { @@ -46378,6 +46402,18 @@ public class FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated runTest("compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt"); } + @Test + @TestMetadata("mfvcInterface.kt") + public void testMfvcInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterface.kt"); + } + + @Test + @TestMetadata("mfvcInterfaceJvmDefault.kt") + public void testMfvcInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterfaceJvmDefault.kt"); + } + @Test @TestMetadata("mfvcKt61304.kt") public void testMfvcKt61304() throws Exception { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java index 0f29bf816ad..f95c3fd56c0 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java @@ -46264,6 +46264,18 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo runTest("compiler/testData/codegen/box/reflection/callBy/boundJvmStaticInObject.kt"); } + @Test + @TestMetadata("brokenDefaultParametersFromDifferentFunctions.kt") + public void testBrokenDefaultParametersFromDifferentFunctions() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctions.kt"); + } + + @Test + @TestMetadata("brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt") + public void testBrokenDefaultParametersFromDifferentFunctionsJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt"); + } + @Test @TestMetadata("companionObject.kt") public void testCompanionObject() throws Exception { @@ -46312,6 +46324,18 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt"); } + @Test + @TestMetadata("inlineClassInterface.kt") + public void testInlineClassInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterface.kt"); + } + + @Test + @TestMetadata("inlineClassInterfaceJvmDefault.kt") + public void testInlineClassInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterfaceJvmDefault.kt"); + } + @Test @TestMetadata("inlineClassMembers.kt") public void testInlineClassMembers() throws Exception { @@ -46378,6 +46402,18 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo runTest("compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt"); } + @Test + @TestMetadata("mfvcInterface.kt") + public void testMfvcInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterface.kt"); + } + + @Test + @TestMetadata("mfvcInterfaceJvmDefault.kt") + public void testMfvcInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterfaceJvmDefault.kt"); + } + @Test @TestMetadata("mfvcKt61304.kt") public void testMfvcKt61304() throws Exception { diff --git a/compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctions.kt b/compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctions.kt new file mode 100644 index 00000000000..6d89f3aab24 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctions.kt @@ -0,0 +1,60 @@ +// TARGET_BACKEND: JVM_IR +// WITH_REFLECT +// LANGUAGE: +ValueClasses +// !JVM_DEFAULT_MODE: disable + +import kotlin.test.assertEquals +import kotlin.reflect.full.instanceParameter + +interface I1 { + fun f(i1: Int = 1, i2: Int): Int +} + +interface I2 { + fun f(i1: Int, i2: Int = 2): Int +} + +data class DC(val x: Int, val y: Int) : I1, I2 { + override fun f(i1: Int, i2: Int) = x + y + i1 +} + +fun dataClass() { + val unbounded = DC::f + assertEquals(111, unbounded.callBy(mapOf(unbounded.instanceParameter!! to DC(10, 100)))) + + val bounded = DC(10, 100)::f + assertEquals(111, bounded.callBy(mapOf())) +} + +@JvmInline +value class VC(val x: Int, val y: Int) : I1, I2 { + override fun f(i1: Int, i2: Int) = x + y + i1 +} + +fun valueClass() { + val unbounded = VC::f + assertEquals(111, unbounded.callBy(mapOf(unbounded.instanceParameter!! to VC(10, 100)))) + + val bounded = VC(10, 100)::f + assertEquals(111, bounded.callBy(mapOf())) +} + +@JvmInline +value class IC(val x: Int) : I1, I2 { + override fun f(i1: Int, i2: Int) = x + i1 +} + +fun inlineClass() { + val unbounded = IC::f + assertEquals(11, unbounded.callBy(mapOf(unbounded.instanceParameter!! to IC(10)))) + + val bounded = IC(10)::f + assertEquals(11, bounded.callBy(mapOf())) +} + +fun box(): String { + dataClass() + inlineClass() + valueClass() + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt b/compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt new file mode 100644 index 00000000000..44a4707d1cb --- /dev/null +++ b/compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt @@ -0,0 +1,60 @@ +// TARGET_BACKEND: JVM_IR +// WITH_REFLECT +// LANGUAGE: +ValueClasses +// !JVM_DEFAULT_MODE: all + +import kotlin.test.assertEquals +import kotlin.reflect.full.instanceParameter + +interface I1 { + fun f(i1: Int = 1, i2: Int): Int +} + +interface I2 { + fun f(i1: Int, i2: Int = 2): Int +} + +data class DC(val x: Int, val y: Int) : I1, I2 { + override fun f(i1: Int, i2: Int) = x + y + i1 +} + +fun dataClass() { + val unbounded = DC::f + assertEquals(111, unbounded.callBy(mapOf(unbounded.instanceParameter!! to DC(10, 100)))) + + val bounded = DC(10, 100)::f + assertEquals(111, bounded.callBy(mapOf())) +} + +@JvmInline +value class VC(val x: Int, val y: Int) : I1, I2 { + override fun f(i1: Int, i2: Int) = x + y + i1 +} + +fun valueClass() { + val unbounded = VC::f + assertEquals(111, unbounded.callBy(mapOf(unbounded.instanceParameter!! to VC(10, 100)))) + + val bounded = VC(10, 100)::f + assertEquals(111, bounded.callBy(mapOf())) +} + +@JvmInline +value class IC(val x: Int) : I1, I2 { + override fun f(i1: Int, i2: Int) = x + i1 +} + +fun inlineClass() { + val unbounded = IC::f + assertEquals(11, unbounded.callBy(mapOf(unbounded.instanceParameter!! to IC(10)))) + + val bounded = IC(10)::f + assertEquals(11, bounded.callBy(mapOf())) +} + +fun box(): String { + dataClass() + inlineClass() + valueClass() + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/callBy/inlineClassInterface.kt b/compiler/testData/codegen/box/reflection/callBy/inlineClassInterface.kt new file mode 100644 index 00000000000..e935e3e88a8 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/callBy/inlineClassInterface.kt @@ -0,0 +1,44 @@ +// TARGET_BACKEND: JVM_IR +// WITH_REFLECT +// !JVM_DEFAULT_MODE: disable + + +import kotlin.test.assertEquals +import kotlin.reflect.full.instanceParameter + + +interface IIC { + fun f(i1: Int = 1): Int +} + +inline class IC(val x: Int) : IIC { + override fun f(i1: Int) = x + i1 +} + +interface Outer { + @JvmInline + value class DefaultImpls(val x: Int) { + fun f(i1: Int = 1) = x + i1 + } +} + +fun box(): String { + val unbounded1 = IC::f + assertEquals(3, unbounded1.callBy(mapOf(unbounded1.instanceParameter!! to IC(2)))) + assertEquals(7, unbounded1.callBy(mapOf(unbounded1.instanceParameter!! to IC(2), unbounded1.parameters[1] to 5))) + + val bounded1 = IC(2)::f + assertEquals(3, bounded1.callBy(mapOf())) + assertEquals(7, bounded1.callBy(mapOf(bounded1.parameters.first() to 5))) + + + val unbounded2 = Outer.DefaultImpls::f + assertEquals(3, unbounded2.callBy(mapOf(unbounded2.instanceParameter!! to Outer.DefaultImpls(2)))) + assertEquals(7, unbounded2.callBy(mapOf(unbounded2.instanceParameter!! to Outer.DefaultImpls(2), unbounded2.parameters[1] to 5))) + + val bounded2 = Outer.DefaultImpls(2)::f + assertEquals(3, bounded2.callBy(mapOf())) + assertEquals(7, bounded2.callBy(mapOf(bounded2.parameters.first() to 5))) + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/callBy/inlineClassInterfaceJvmDefault.kt b/compiler/testData/codegen/box/reflection/callBy/inlineClassInterfaceJvmDefault.kt new file mode 100644 index 00000000000..0af4f576450 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/callBy/inlineClassInterfaceJvmDefault.kt @@ -0,0 +1,45 @@ +// TARGET_BACKEND: JVM_IR +// WITH_REFLECT +// !JVM_DEFAULT_MODE: all +// IGNORE_BACKEND: ANDROID + + +import kotlin.test.assertEquals +import kotlin.reflect.full.instanceParameter + + +interface IIC { + fun f(i1: Int = 1): Int +} + +inline class IC(val x: Int) : IIC { + override fun f(i1: Int) = x + i1 +} + +interface Outer { + @JvmInline + value class DefaultImpls(val x: Int) { + fun f(i1: Int = 1) = x + i1 + } +} + +fun box(): String { + val unbounded1 = IC::f + assertEquals(3, unbounded1.callBy(mapOf(unbounded1.instanceParameter!! to IC(2)))) + assertEquals(7, unbounded1.callBy(mapOf(unbounded1.instanceParameter!! to IC(2), unbounded1.parameters[1] to 5))) + + val bounded1 = IC(2)::f + assertEquals(3, bounded1.callBy(mapOf())) + assertEquals(7, bounded1.callBy(mapOf(bounded1.parameters.first() to 5))) + + + val unbounded2 = Outer.DefaultImpls::f + assertEquals(3, unbounded2.callBy(mapOf(unbounded2.instanceParameter!! to Outer.DefaultImpls(2)))) + assertEquals(7, unbounded2.callBy(mapOf(unbounded2.instanceParameter!! to Outer.DefaultImpls(2), unbounded2.parameters[1] to 5))) + + val bounded2 = Outer.DefaultImpls(2)::f + assertEquals(3, bounded2.callBy(mapOf())) + assertEquals(7, bounded2.callBy(mapOf(bounded2.parameters.first() to 5))) + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/callBy/mfvcInterface.kt b/compiler/testData/codegen/box/reflection/callBy/mfvcInterface.kt new file mode 100644 index 00000000000..ad0044e033c --- /dev/null +++ b/compiler/testData/codegen/box/reflection/callBy/mfvcInterface.kt @@ -0,0 +1,46 @@ +// TARGET_BACKEND: JVM_IR +// WITH_REFLECT +// LANGUAGE: +ValueClasses +// !JVM_DEFAULT_MODE: disable + + +import kotlin.test.assertEquals +import kotlin.reflect.full.instanceParameter + +interface IVC { + fun f(i1: Int = 1): Int +} + +@JvmInline +value class VC(val x: Int, val y: Int) : IVC { + override fun f(i1: Int) = x + y + i1 +} + +interface Outer { + @JvmInline + value class DefaultImpls(val x: Int, val y: Int) { + fun f(i1: Int = 1) = x + y + i1 + } +} + + +fun box(): String { + val unbounded1 = VC::f + assertEquals(8, unbounded1.callBy(mapOf(unbounded1.instanceParameter!! to VC(2, 5)))) + assertEquals(12, unbounded1.callBy(mapOf(unbounded1.instanceParameter!! to VC(2, 5), unbounded1.parameters[1] to 5))) + + val bounded1 = VC(2, 5)::f + assertEquals(8, bounded1.callBy(mapOf())) + assertEquals(12, bounded1.callBy(mapOf(bounded1.parameters.first() to 5))) + + + val unbounded2 = Outer.DefaultImpls::f + assertEquals(8, unbounded2.callBy(mapOf(unbounded2.instanceParameter!! to Outer.DefaultImpls(2, 5)))) + assertEquals(12, unbounded2.callBy(mapOf(unbounded2.instanceParameter!! to Outer.DefaultImpls(2, 5), unbounded2.parameters[1] to 5))) + + val bounded2 = Outer.DefaultImpls(2, 5)::f + assertEquals(8, bounded2.callBy(mapOf())) + assertEquals(12, bounded2.callBy(mapOf(bounded2.parameters.first() to 5))) + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/callBy/mfvcInterfaceJvmDefault.kt b/compiler/testData/codegen/box/reflection/callBy/mfvcInterfaceJvmDefault.kt new file mode 100644 index 00000000000..7698302032d --- /dev/null +++ b/compiler/testData/codegen/box/reflection/callBy/mfvcInterfaceJvmDefault.kt @@ -0,0 +1,46 @@ +// TARGET_BACKEND: JVM_IR +// WITH_REFLECT +// LANGUAGE: +ValueClasses +// !JVM_DEFAULT_MODE: all + + +import kotlin.test.assertEquals +import kotlin.reflect.full.instanceParameter + +interface IVC { + fun f(i1: Int = 1): Int +} + +@JvmInline +value class VC(val x: Int, val y: Int) : IVC { + override fun f(i1: Int) = x + y + i1 +} + +interface Outer { + @JvmInline + value class DefaultImpls(val x: Int, val y: Int) { + fun f(i1: Int = 1) = x + y + i1 + } +} + + +fun box(): String { + val unbounded1 = VC::f + assertEquals(8, unbounded1.callBy(mapOf(unbounded1.instanceParameter!! to VC(2, 5)))) + assertEquals(12, unbounded1.callBy(mapOf(unbounded1.instanceParameter!! to VC(2, 5), unbounded1.parameters[1] to 5))) + + val bounded1 = VC(2, 5)::f + assertEquals(8, bounded1.callBy(mapOf())) + assertEquals(12, bounded1.callBy(mapOf(bounded1.parameters.first() to 5))) + + + val unbounded2 = Outer.DefaultImpls::f + assertEquals(8, unbounded2.callBy(mapOf(unbounded2.instanceParameter!! to Outer.DefaultImpls(2, 5)))) + assertEquals(12, unbounded2.callBy(mapOf(unbounded2.instanceParameter!! to Outer.DefaultImpls(2, 5), unbounded2.parameters[1] to 5))) + + val bounded2 = Outer.DefaultImpls(2, 5)::f + assertEquals(8, bounded2.callBy(mapOf())) + assertEquals(12, bounded2.callBy(mapOf(bounded2.parameters.first() to 5))) + + return "OK" +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/JvmAbiConsistencyTestBoxGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/JvmAbiConsistencyTestBoxGenerated.java index 25d92434a69..cb74ac846d0 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/JvmAbiConsistencyTestBoxGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/JvmAbiConsistencyTestBoxGenerated.java @@ -45580,6 +45580,18 @@ public class JvmAbiConsistencyTestBoxGenerated extends AbstractJvmAbiConsistency runTest("compiler/testData/codegen/box/reflection/callBy/boundJvmStaticInObject.kt"); } + @Test + @TestMetadata("brokenDefaultParametersFromDifferentFunctions.kt") + public void testBrokenDefaultParametersFromDifferentFunctions() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctions.kt"); + } + + @Test + @TestMetadata("brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt") + public void testBrokenDefaultParametersFromDifferentFunctionsJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt"); + } + @Test @TestMetadata("companionObject.kt") public void testCompanionObject() throws Exception { @@ -45628,6 +45640,18 @@ public class JvmAbiConsistencyTestBoxGenerated extends AbstractJvmAbiConsistency runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt"); } + @Test + @TestMetadata("inlineClassInterface.kt") + public void testInlineClassInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterface.kt"); + } + + @Test + @TestMetadata("inlineClassInterfaceJvmDefault.kt") + public void testInlineClassInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterfaceJvmDefault.kt"); + } + @Test @TestMetadata("inlineClassMembers.kt") public void testInlineClassMembers() throws Exception { @@ -45694,6 +45718,18 @@ public class JvmAbiConsistencyTestBoxGenerated extends AbstractJvmAbiConsistency runTest("compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt"); } + @Test + @TestMetadata("mfvcInterface.kt") + public void testMfvcInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterface.kt"); + } + + @Test + @TestMetadata("mfvcInterfaceJvmDefault.kt") + public void testMfvcInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterfaceJvmDefault.kt"); + } + @Test @TestMetadata("mfvcKt61304.kt") public void testMfvcKt61304() throws Exception { 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 fb7a7f5f813..a5fbd7cc635 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 @@ -45580,6 +45580,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/reflection/callBy/boundJvmStaticInObject.kt"); } + @Test + @TestMetadata("brokenDefaultParametersFromDifferentFunctions.kt") + public void testBrokenDefaultParametersFromDifferentFunctions() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctions.kt"); + } + + @Test + @TestMetadata("brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt") + public void testBrokenDefaultParametersFromDifferentFunctionsJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt"); + } + @Test @TestMetadata("companionObject.kt") public void testCompanionObject() throws Exception { @@ -45628,6 +45640,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt"); } + @Test + @TestMetadata("inlineClassInterface.kt") + public void testInlineClassInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterface.kt"); + } + + @Test + @TestMetadata("inlineClassInterfaceJvmDefault.kt") + public void testInlineClassInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterfaceJvmDefault.kt"); + } + @Test @TestMetadata("inlineClassMembers.kt") public void testInlineClassMembers() throws Exception { @@ -45694,6 +45718,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt"); } + @Test + @TestMetadata("mfvcInterface.kt") + public void testMfvcInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterface.kt"); + } + + @Test + @TestMetadata("mfvcInterfaceJvmDefault.kt") + public void testMfvcInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterfaceJvmDefault.kt"); + } + @Test @TestMetadata("mfvcKt61304.kt") public void testMfvcKt61304() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java index 3aa1efe6f29..117babb43c4 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java @@ -45580,6 +45580,18 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack runTest("compiler/testData/codegen/box/reflection/callBy/boundJvmStaticInObject.kt"); } + @Test + @TestMetadata("brokenDefaultParametersFromDifferentFunctions.kt") + public void testBrokenDefaultParametersFromDifferentFunctions() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctions.kt"); + } + + @Test + @TestMetadata("brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt") + public void testBrokenDefaultParametersFromDifferentFunctionsJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt"); + } + @Test @TestMetadata("companionObject.kt") public void testCompanionObject() throws Exception { @@ -45628,6 +45640,18 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt"); } + @Test + @TestMetadata("inlineClassInterface.kt") + public void testInlineClassInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterface.kt"); + } + + @Test + @TestMetadata("inlineClassInterfaceJvmDefault.kt") + public void testInlineClassInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterfaceJvmDefault.kt"); + } + @Test @TestMetadata("inlineClassMembers.kt") public void testInlineClassMembers() throws Exception { @@ -45694,6 +45718,18 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack runTest("compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt"); } + @Test + @TestMetadata("mfvcInterface.kt") + public void testMfvcInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterface.kt"); + } + + @Test + @TestMetadata("mfvcInterfaceJvmDefault.kt") + public void testMfvcInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterfaceJvmDefault.kt"); + } + @Test @TestMetadata("mfvcKt61304.kt") public void testMfvcKt61304() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 25d9d3570d2..1b1c600b7c7 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -36279,6 +36279,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/reflection/callBy/boundJvmStaticInObject.kt"); } + @TestMetadata("brokenDefaultParametersFromDifferentFunctions.kt") + public void testBrokenDefaultParametersFromDifferentFunctions() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctions.kt"); + } + + @TestMetadata("brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt") + public void testBrokenDefaultParametersFromDifferentFunctionsJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctionsJvmDefault.kt"); + } + @TestMetadata("companionObject.kt") public void testCompanionObject() throws Exception { runTest("compiler/testData/codegen/box/reflection/callBy/companionObject.kt"); @@ -36319,6 +36329,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt"); } + @TestMetadata("inlineClassInterface.kt") + public void testInlineClassInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterface.kt"); + } + + @TestMetadata("inlineClassInterfaceJvmDefault.kt") + public void testInlineClassInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassInterfaceJvmDefault.kt"); + } + @TestMetadata("inlineClassMembers.kt") public void testInlineClassMembers() throws Exception { runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassMembers.kt"); @@ -36374,6 +36394,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt"); } + @TestMetadata("mfvcInterface.kt") + public void testMfvcInterface() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterface.kt"); + } + + @TestMetadata("mfvcInterfaceJvmDefault.kt") + public void testMfvcInterfaceJvmDefault() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/mfvcInterfaceJvmDefault.kt"); + } + @TestMetadata("mfvcKt61304.kt") public void testMfvcKt61304() throws Exception { runTest("compiler/testData/codegen/box/reflection/callBy/mfvcKt61304.kt"); diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt index 942942fc038..a8b5784e13c 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt @@ -19,7 +19,10 @@ package kotlin.reflect.jvm.internal import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeAsSequence +import org.jetbrains.kotlin.resolve.isInlineClassType import org.jetbrains.kotlin.resolve.isMultiFieldValueClass +import org.jetbrains.kotlin.resolve.isValueClass import org.jetbrains.kotlin.resolve.jvm.shouldHideConstructorDueToValueClassTypeValueParameters import java.lang.reflect.Constructor import java.lang.reflect.Member @@ -100,12 +103,17 @@ internal class KFunctionImpl private constructor( } override val defaultCaller: Caller<*>? by lazy(PUBLICATION) defaultCaller@{ - val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor) - val member: Member? = when (jvmSignature) { - is KotlinFunction -> { + val member: Member? = when (val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)) { + is KotlinFunction -> run { if (descriptor.let { it.containingDeclaration.isMultiFieldValueClass() && it is ConstructorDescriptor && it.isPrimary }) { throw KotlinReflectionInternalError("${descriptor.containingDeclaration} cannot have default arguments") } + + getFunctionWithDefaultParametersForValueClassOverride(descriptor)?.let { defaultImplsFunction -> + val replacingJvmSignature = RuntimeTypeMapper.mapSignature(defaultImplsFunction) as KotlinFunction + return@run container.findDefaultMethod(replacingJvmSignature.methodName, replacingJvmSignature.methodDesc, true) + } + container.findDefaultMethod(jvmSignature.methodName, jvmSignature.methodDesc, !Modifier.isStatic(caller.member!!.modifiers)) } is KotlinConstructor -> { @@ -141,11 +149,32 @@ internal class KFunctionImpl private constructor( }?.createValueClassAwareCallerIfNeeded(descriptor, isDefault = true) } + private fun getFunctionWithDefaultParametersForValueClassOverride(descriptor: FunctionDescriptor): FunctionDescriptor? { + if ( + descriptor.valueParameters.none { it.declaresDefaultValue() } && + descriptor.containingDeclaration.isValueClass() && + Modifier.isStatic(caller.member!!.modifiers) + ) { + // firstOrNull is used to mimic the wrong behaviour of regular class reflection as KT-40327 is not fixed. + // The behaviours equality is currently backed by codegen/box/reflection/callBy/brokenDefaultParametersFromDifferentFunctions.kt. + return descriptor.overriddenTreeAsSequence(useOriginal = false) + .firstOrNull { function -> function.valueParameters.any { it.declaresDefaultValue() } } as? FunctionDescriptor + } + return null + } + private val boundReceiver get() = rawBoundReceiver.coerceToExpectedReceiverType(descriptor) + // boundReceiver is unboxed receiver when the receiver is inline class. + // However, when the expected dispatch receiver type is an interface, + // the member belongs to the interface/DefaultImpls, so the receiver should not be unboxed. + private fun useBoxedBoundReceiver(member: Method) = + descriptor.dispatchReceiverParameter?.type?.isInlineClassType() == true && member.parameterTypes.firstOrNull()?.isInterface == true + private fun createStaticMethodCaller(member: Method) = - if (isBound) CallerImpl.Method.BoundStatic(member, boundReceiver) else CallerImpl.Method.Static(member) + if (isBound) CallerImpl.Method.BoundStatic(member, if (useBoxedBoundReceiver(member)) rawBoundReceiver else boundReceiver) + else CallerImpl.Method.Static(member) private fun createJvmStaticInObjectCaller(member: Method) = if (isBound) CallerImpl.Method.BoundJvmStaticInObject(member) else CallerImpl.Method.JvmStaticInObject(member) diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KParameterImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KParameterImpl.kt index b6319c36624..d9b0839aa5d 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KParameterImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KParameterImpl.kt @@ -27,7 +27,7 @@ internal class KParameterImpl( val callable: KCallableImpl<*>, override val index: Int, override val kind: KParameter.Kind, - computeDescriptor: () -> ParameterDescriptor + computeDescriptor: () -> ParameterDescriptor, ) : KParameter { private val descriptor: ParameterDescriptor by ReflectProperties.lazySoft(computeDescriptor) @@ -78,8 +78,14 @@ internal class KParameterImpl( } else { when (val caller = callable.caller) { is ValueClassAwareCaller -> { - val slice = caller.getRealSlicesOfParameters(index) - val parameterTypes = caller.parameterTypes.slice(slice) + val parameterTypes = if (callable.isBound) { + val slice = caller.getRealSlicesOfParameters(index + 1) + val offset = caller.getRealSlicesOfParameters(0).last + 1 + caller.parameterTypes.slice((slice.first - offset)..(slice.last - offset)) + } else { + val slice = caller.getRealSlicesOfParameters(index) + caller.parameterTypes.slice(slice) + } compoundType(*parameterTypes.toTypedArray()) } is ValueClassAwareCaller.MultiFieldValueClassPrimaryConstructorCaller -> diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/ValueClassAwareCaller.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/ValueClassAwareCaller.kt index bb460d04500..b5e6df649ed 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/ValueClassAwareCaller.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/ValueClassAwareCaller.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.SimpleType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.asSimpleType +import org.jetbrains.kotlin.types.typeUtil.makeNullable import java.lang.reflect.Member import java.lang.reflect.Method import java.lang.reflect.Type @@ -28,7 +29,7 @@ import kotlin.reflect.jvm.internal.toJavaClass /** * A caller that is used whenever the declaration has value classes in its parameter types or inline class in return type. - * Each argument of an value class type is unboxed, and the return value (if it's of an inline class type) is boxed. + * Each argument of a value class type is unboxed, and the return value (if it's of an inline class type) is boxed. */ internal class ValueClassAwareCaller( descriptor: CallableMemberDescriptor, @@ -38,7 +39,11 @@ internal class ValueClassAwareCaller( private val caller: Caller = if (oldCaller is CallerImpl.Method.BoundStatic) { val receiverType = (descriptor.extensionReceiverParameter ?: descriptor.dispatchReceiverParameter)?.type - if (receiverType != null && receiverType.needsMfvcFlattening()) { + if ( + receiverType != null && + receiverType.needsMfvcFlattening() && + (!isDefault || descriptor.valueParameters.any { it.declaresDefaultValue() }) + ) { val unboxMethods = getMfvcUnboxMethods(receiverType.asSimpleType())!! val boundReceiverComponents = unboxMethods.map { it.invoke(oldCaller.boundReceiver) }.toTypedArray() @Suppress("UNCHECKED_CAST") @@ -103,7 +108,7 @@ internal class ValueClassAwareCaller( val flattenedShift = if (caller is CallerImpl.Method.BoundStaticMultiFieldValueClass) -caller.receiverComponentsCount else shift - val kotlinParameterTypes: List = makeKotlinParameterTypes(descriptor) { isValueClass() } + val kotlinParameterTypes: List = makeKotlinParameterTypes(descriptor, caller.member) { isValueClass() } fun typeSize(type: KotlinType): Int = getMfvcUnboxMethods(type.asSimpleType())?.size ?: 1 @@ -184,7 +189,7 @@ internal class ValueClassAwareCaller( if (index in range) { val method = unbox[index]?.single() val arg = args[index] - // Note that arg may be null in case we're calling a $default method, and it's an optional parameter of a inline class type + // Note that arg may be null in case we're calling a $default method, and it's an optional parameter of an inline class type when { method == null -> arg arg != null -> method.invoke(arg) @@ -270,7 +275,7 @@ private fun Caller<*>.checkParametersSize( } private fun makeKotlinParameterTypes( - descriptor: CallableMemberDescriptor, isSpecificClass: ClassDescriptor.() -> Boolean + descriptor: CallableMemberDescriptor, member: Member?, isSpecificClass: ClassDescriptor.() -> Boolean ): List = ArrayList().also { kotlinParameterTypes -> val extensionReceiverType = descriptor.extensionReceiverParameter?.type if (extensionReceiverType != null) { @@ -283,13 +288,32 @@ private fun makeKotlinParameterTypes( } else { val containingDeclaration = descriptor.containingDeclaration if (containingDeclaration is ClassDescriptor && containingDeclaration.isSpecificClass()) { - kotlinParameterTypes.add(containingDeclaration.defaultType) + if (member?.acceptsBoxedReceiverParameter() == true) { + // hack to forbid unboxing dispatchReceiver if it is used upcasted + // kotlinParameterTypes are used to determine shifts and calls according to whether type is MFVC/IC or not. + // If it is a MFVC/IC, boxes are unboxed. If the actual called member lies in the interface/DefaultImpls class, + // it accepts a boxed parameter as ex-dispatch receiver. Making the type nullable allows to prevent unboxing in this case. + kotlinParameterTypes.add(containingDeclaration.defaultType.makeNullable()) + } else { + kotlinParameterTypes.add(containingDeclaration.defaultType) + } } } descriptor.valueParameters.mapTo(kotlinParameterTypes, ValueParameterDescriptor::getType) } +private fun Member.acceptsBoxedReceiverParameter(): Boolean { + // Method implementation can be placed either in + // * the value class itself, + // * interface$DefaultImpls, + // * interface default method (Java 8+). + // Here we need to understand that it is the second or the third case. Both of the cases cannot be value classes, + // so the simplest solution is to check declaringClass for being a value class. + val clazz = declaringClass ?: return false + return !clazz.kotlin.isValue +} + internal fun Caller.createValueClassAwareCallerIfNeeded( descriptor: CallableMemberDescriptor, isDefault: Boolean = false