diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 4efc6d6f598..e10bea12101 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -23660,6 +23660,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/reflection/callBy/extensionFunction.kt"); } + @TestMetadata("inlineClassDefaultArguments.kt") + public void testInlineClassDefaultArguments() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassDefaultArguments.kt"); + } + @TestMetadata("inlineClassFunctionsAndConstructors.kt") public void testInlineClassFunctionsAndConstructors() throws Exception { runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt"); diff --git a/compiler/testData/codegen/box/reflection/callBy/inlineClassDefaultArguments.kt b/compiler/testData/codegen/box/reflection/callBy/inlineClassDefaultArguments.kt new file mode 100644 index 00000000000..6d680cbb21c --- /dev/null +++ b/compiler/testData/codegen/box/reflection/callBy/inlineClassDefaultArguments.kt @@ -0,0 +1,10 @@ +// IGNORE_BACKEND: JS_IR, JS, NATIVE +// WITH_REFLECT + +inline class A(val x: Int) + +fun test(x: A = A(0)) = "OK" + +fun box(): String { + return (::test).callBy(mapOf()) +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index ab679bcc0d8..7b6ded59f65 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -25246,6 +25246,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/reflection/callBy/extensionFunction.kt"); } + @TestMetadata("inlineClassDefaultArguments.kt") + public void testInlineClassDefaultArguments() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassDefaultArguments.kt"); + } + @TestMetadata("inlineClassFunctionsAndConstructors.kt") public void testInlineClassFunctionsAndConstructors() throws Exception { runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index f1e1493a3ce..f8014d9147e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -24063,6 +24063,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/reflection/callBy/extensionFunction.kt"); } + @TestMetadata("inlineClassDefaultArguments.kt") + public void testInlineClassDefaultArguments() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassDefaultArguments.kt"); + } + @TestMetadata("inlineClassFunctionsAndConstructors.kt") public void testInlineClassFunctionsAndConstructors() throws Exception { runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index b2de0adb413..0b07f3fb5d7 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -23660,6 +23660,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/reflection/callBy/extensionFunction.kt"); } + @TestMetadata("inlineClassDefaultArguments.kt") + public void testInlineClassDefaultArguments() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassDefaultArguments.kt"); + } + @TestMetadata("inlineClassFunctionsAndConstructors.kt") public void testInlineClassFunctionsAndConstructors() throws Exception { runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt"); diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt index dc6d90e4d90..0198cb7f41e 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt @@ -132,7 +132,9 @@ internal abstract class KCallableImpl : KCallable { arguments.add(args[parameter]) } parameter.isOptional -> { - arguments.add(defaultPrimitiveValue(parameter.type.javaType)) + // For inline class types, the javaType refers to the underlying type of the inline class, + // but we have to pass null in order to mark the argument as absent for InlineClassAwareCaller. + arguments.add(if (parameter.type.isInlineClassType) null else defaultPrimitiveValue(parameter.type.javaType)) mask = mask or (1 shl (index % Integer.SIZE)) anyOptional = true } @@ -192,22 +194,6 @@ internal abstract class KCallableImpl : KCallable { } } - private fun defaultPrimitiveValue(type: Type): Any? = - if (type is Class<*> && type.isPrimitive) { - when (type) { - Boolean::class.java -> false - Char::class.java -> 0.toChar() - Byte::class.java -> 0.toByte() - Short::class.java -> 0.toShort() - Int::class.java -> 0 - Float::class.java -> 0f - Long::class.java -> 0L - Double::class.java -> 0.0 - Void.TYPE -> throw IllegalStateException("Parameter with void type is illegal") - else -> throw UnsupportedOperationException("Unknown primitive: $type") - } - } else null - private fun defaultEmptyArray(type: KType): Any = type.jvmErasure.java.run { if (isArray) ReflectArray.newInstance(componentType, 0) diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/InlineClassAwareCaller.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/InlineClassAwareCaller.kt index 67d2ced882b..4e867a5bbf7 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/InlineClassAwareCaller.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/InlineClassAwareCaller.kt @@ -17,6 +17,7 @@ import java.lang.reflect.Member import java.lang.reflect.Method import java.lang.reflect.Type import kotlin.reflect.jvm.internal.KotlinReflectionInternalError +import kotlin.reflect.jvm.internal.defaultPrimitiveValue import kotlin.reflect.jvm.internal.toJavaClass /** @@ -127,9 +128,15 @@ internal class InlineClassAwareCaller( val method = unbox[index] 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 an inline class type - unboxed[index] = - if (method != null && arg != null) method.invoke(arg) - else arg + unboxed[index] = if (method != null) { + if (arg != null) { + method.invoke(arg) + } else { + defaultPrimitiveValue(method.returnType) + } + } else { + arg + } } val result = caller.call(unboxed) diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/util.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/util.kt index b3a4d25a770..5eee08ee1dd 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/util.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/util.kt @@ -46,6 +46,9 @@ import org.jetbrains.kotlin.descriptors.runtime.components.tryLoadClass import org.jetbrains.kotlin.descriptors.runtime.structure.ReflectJavaAnnotation import org.jetbrains.kotlin.descriptors.runtime.structure.ReflectJavaClass import org.jetbrains.kotlin.descriptors.runtime.structure.safeClassLoader +import org.jetbrains.kotlin.resolve.isInlineClassType +import java.lang.reflect.Type +import kotlin.reflect.KType internal val JVM_STATIC = FqName("kotlin.jvm.JvmStatic") @@ -195,3 +198,22 @@ internal fun deserializeToDescriptor( ) return MemberDeserializer(context).createDescriptor(proto) } + +internal val KType.isInlineClassType: Boolean + get() = (this as? KTypeImpl)?.type?.isInlineClassType() == true + +internal fun defaultPrimitiveValue(type: Type): Any? = + if (type is Class<*> && type.isPrimitive) { + when (type) { + Boolean::class.java -> false + Char::class.java -> 0.toChar() + Byte::class.java -> 0.toByte() + Short::class.java -> 0.toShort() + Int::class.java -> 0 + Float::class.java -> 0f + Long::class.java -> 0L + Double::class.java -> 0.0 + Void.TYPE -> throw IllegalStateException("Parameter with void type is illegal") + else -> throw UnsupportedOperationException("Unknown primitive: $type") + } + } else null diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index e9084eed1b6..f63c224ad32 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -19911,6 +19911,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/reflection/callBy/extensionFunction.kt"); } + @TestMetadata("inlineClassDefaultArguments.kt") + public void testInlineClassDefaultArguments() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassDefaultArguments.kt"); + } + @TestMetadata("inlineClassFunctionsAndConstructors.kt") public void testInlineClassFunctionsAndConstructors() throws Exception { runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 773649f7c05..f02bce10943 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -19971,6 +19971,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/reflection/callBy/extensionFunction.kt"); } + @TestMetadata("inlineClassDefaultArguments.kt") + public void testInlineClassDefaultArguments() throws Exception { + runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassDefaultArguments.kt"); + } + @TestMetadata("inlineClassFunctionsAndConstructors.kt") public void testInlineClassFunctionsAndConstructors() throws Exception { runTest("compiler/testData/codegen/box/reflection/callBy/inlineClassFunctionsAndConstructors.kt");