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 81bad638c4e..7462f03ba8a 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 @@ -19000,6 +19000,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/intN.kt"); } + @Test + @TestMetadata("null.kt") + public void testNull() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/null.kt"); + } + @Test @TestMetadata("result.kt") public void testResult() throws Exception { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 78901359e27..159ef531a65 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -16,8 +16,6 @@ import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound import org.jetbrains.kotlin.backend.jvm.ir.isInlineClassType import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry import org.jetbrains.kotlin.backend.jvm.lower.constantValue -import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.isInlineCallableReference -import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.isMappedToPrimitive import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.requiresMangling import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass import org.jetbrains.kotlin.backend.jvm.lower.isMultifileBridge @@ -648,22 +646,9 @@ class ExpressionCodegen( val type = frameMap.typeOf(expression.symbol) mv.load(findLocalIndex(expression.symbol), type) unboxResultIfNeeded(expression) - unboxInlineClassArgumentOfInlineCallableReference(expression) return MaterialValue(this, type, expression.type) } - // JVM_IR generates inline callable differently from the old backend: - // it generates them as normal functions and not objects. - // Thus, we need to unbox inline class argument with reference underlying type. - private fun unboxInlineClassArgumentOfInlineCallableReference(arg: IrGetValue) { - if (!arg.type.isInlineClassType()) return - if (arg.type.isMappedToPrimitive) return - if (!irFunction.isInlineCallableReference) return - if (irFunction.extensionReceiverParameter?.symbol == arg.symbol) return - if (arg.type.isNullable() && arg.type.makeNotNull().unboxInlineClass().isNullable()) return - StackValue.unboxInlineClass(OBJECT_TYPE, arg.type.erasedUpperBound.defaultType, mv, typeMapper) - } - // We do not mangle functions if Result is the only parameter of the function, // thus, if the function overrides generic parameter, its argument is boxed and there is no // bridge to unbox it. Instead, we unbox it in the non-mangled function manually. diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt index 68217d80f17..9dac9f6f6bf 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt @@ -201,27 +201,30 @@ class IrExpressionLambdaImpl( private val loweredMethod = codegen.methodSignatureMapper.mapAsmMethod(function) - val capturedParamsInDesc: List = when { - isBoundCallableReference -> loweredMethod.argumentTypes.take(1) - isExtensionLambda -> loweredMethod.argumentTypes.drop(1).take(capturedVars.size) - else -> loweredMethod.argumentTypes.take(capturedVars.size) - } + private val captureParameterIndices: Pair + get() = when { + isBoundCallableReference -> 0 to 1 // (bound receiver, real parameters...) + isExtensionLambda -> 1 to capturedVars.size + 1 // (unbound receiver, captures..., real parameters...) + else -> 0 to capturedVars.size // (captures..., real parameters...) + } + + val capturedParamsInDesc: List = + captureParameterIndices.let { (from, to) -> loweredMethod.argumentTypes.take(to).drop(from) } override val invokeMethod: Method = loweredMethod.let { - val nonCapturedParameters = when { - isBoundCallableReference -> it.argumentTypes.drop(1) - isExtensionLambda -> it.argumentTypes.take(1) + it.argumentTypes.drop(capturedVars.size + 1) - else -> it.argumentTypes.drop(capturedVars.size) - }.toTypedArray() - Method(it.name, it.returnType, nonCapturedParameters) + val (startCapture, endCapture) = captureParameterIndices + Method(it.name, it.returnType, (it.argumentTypes.take(startCapture) + it.argumentTypes.drop(endCapture)).toTypedArray()) } - // TODO: no extension receiver if bound override val invokeMethodParameters: List - get() = function.originalFunction.explicitParameters.map { it.type.toIrBasedKotlinType() } + get() { + val allParameters = function.explicitParameters.map { it.type.toIrBasedKotlinType() } + val (startCapture, endCapture) = captureParameterIndices + return allParameters.take(startCapture) + allParameters.drop(endCapture) + } override val invokeMethodReturnType: KotlinType - get() = function.originalFunction.returnType.toIrBasedKotlinType() // not including COROUTINE_SUSPENDED + get() = function.returnType.toIrBasedKotlinType() override val hasDispatchReceiver: Boolean = false diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt index 6620a1f291a..e2a1eb720a5 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt @@ -13,8 +13,6 @@ import org.jetbrains.kotlin.backend.common.lower.parentsWithSelf import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.ir.* -import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.isInlineCallableReference -import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.isMappedToPrimitive import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass import org.jetbrains.kotlin.backend.jvm.lower.suspendFunctionOriginal import org.jetbrains.kotlin.builtins.StandardNames @@ -62,7 +60,7 @@ class MethodSignatureMapper(private val context: JvmBackendContext) { fun mapFieldSignature(field: IrField): String? { val sw = BothSignatureWriter(BothSignatureWriter.Mode.TYPE) if (field.correspondingPropertySymbol?.owner?.isVar == true) { - writeParameterType(sw, field.type, field, false) + writeParameterType(sw, field.type, field) } else { mapReturnType(field, field.type, sw) } @@ -221,13 +219,6 @@ class MethodSignatureMapper(private val context: JvmBackendContext) { function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_INLINE_CLASS_MEMBER && function.name.asString() == "box-impl" - private fun forceBoxedInlineClassParametersForInliner(function: IrDeclaration, type: IrType, isBoundReceiver: Boolean): Boolean { - if (isBoundReceiver) return false - if (function !is IrSimpleFunction) return false - if (!function.isInlineCallableReference) return false - return type.isInlineClassType() && !type.isMappedToPrimitive - } - fun mapSignatureSkipGeneric(function: IrFunction): JvmMethodSignature = mapSignature(function, true) @@ -252,7 +243,7 @@ class MethodSignatureMapper(private val context: JvmBackendContext) { val receiverParameter = function.extensionReceiverParameter if (receiverParameter != null) { - writeParameter(sw, JvmMethodParameterKind.RECEIVER, receiverParameter.type, function, true) + writeParameter(sw, JvmMethodParameterKind.RECEIVER, receiverParameter.type, function) } for (parameter in function.valueParameters) { @@ -265,7 +256,7 @@ class MethodSignatureMapper(private val context: JvmBackendContext) { if (shouldBoxSingleValueParameterForSpecialCaseOfRemove(function)) parameter.type.makeNullable() else parameter.type - writeParameter(sw, kind, type, function, parameter.symbol == function.extensionReceiverParameter?.symbol) + writeParameter(sw, kind, type, function) } sw.writeReturnType() @@ -331,19 +322,16 @@ class MethodSignatureMapper(private val context: JvmBackendContext) { sw: JvmSignatureWriter, kind: JvmMethodParameterKind, type: IrType, - function: IrFunction, - isReceiver: Boolean + function: IrFunction ) { sw.writeParameterType(kind) - writeParameterType(sw, type, function, isReceiver) + writeParameterType(sw, type, function) sw.writeParameterTypeEnd() } - private fun writeParameterType(sw: JvmSignatureWriter, type: IrType, declaration: IrDeclaration, isReceiver: Boolean) { + private fun writeParameterType(sw: JvmSignatureWriter, type: IrType, declaration: IrDeclaration) { if (sw.skipGenericSignature()) { - if (type.isInlineClassType() && - (declaration.isFromJava() || forceBoxedInlineClassParametersForInliner(declaration, type, isReceiver)) - ) { + if (type.isInlineClassType() && declaration.isFromJava()) { typeMapper.mapType(type, TypeMappingMode.GENERIC_ARGUMENT, sw) } else { typeMapper.mapType(type, TypeMappingMode.DEFAULT, sw) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/InlineClassAbi.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/InlineClassAbi.kt index 84b1e467d6e..a4b006bb96b 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/InlineClassAbi.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/InlineClassAbi.kt @@ -174,11 +174,3 @@ val IrFunction.isInlineClassFieldGetter: Boolean val IrFunction.isPrimaryInlineClassConstructor: Boolean get() = this is IrConstructor && isPrimary && constructedClass.isInline - -val IrFunction.isInlineCallableReference: Boolean - get() = origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA && name.asString().contains("\$$STUB_FOR_INLINING") - -val IrType.isMappedToPrimitive: Boolean - get() = isInlineClassType() && - !(isNullable() && makeNotNull().unboxInlineClass().isNullable()) && - makeNotNull().unboxInlineClass().isPrimitiveType() diff --git a/compiler/testData/codegen/box/inlineClasses/callableReferences/let/null.kt b/compiler/testData/codegen/box/inlineClasses/callableReferences/let/null.kt new file mode 100644 index 00000000000..85a7775c0e1 --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/callableReferences/let/null.kt @@ -0,0 +1,5 @@ +inline class Value(val value: Any) + +fun foo(value: Value?) = value?.value as String? + +fun box(): String = (null as Value?).let(::foo) ?: "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 32a1e0b8ae9..1f1651d000d 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 @@ -18976,6 +18976,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/intN.kt"); } + @Test + @TestMetadata("null.kt") + public void testNull() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/null.kt"); + } + @Test @TestMetadata("result.kt") public void testResult() 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 682875ae2f5..cb8dfdd1df4 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 @@ -19000,6 +19000,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/intN.kt"); } + @Test + @TestMetadata("null.kt") + public void testNull() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/null.kt"); + } + @Test @TestMetadata("result.kt") public void testResult() 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 3ee9e94af0d..5c0dd436abb 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -15747,6 +15747,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/intN.kt"); } + @TestMetadata("null.kt") + public void testNull() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/null.kt"); + } + @TestMetadata("result.kt") public void testResult() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/result.kt"); 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 81e5e02366a..ba604aa904e 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 @@ -13861,6 +13861,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/intN.kt"); } + @TestMetadata("null.kt") + public void testNull() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/null.kt"); + } + @TestMetadata("result.kt") public void testResult() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/result.kt"); 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 11ad13d4901..e81b15e1241 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 @@ -13272,6 +13272,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/intN.kt"); } + @TestMetadata("null.kt") + public void testNull() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/null.kt"); + } + @TestMetadata("result.kt") public void testResult() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/result.kt"); 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 d1ba779e0d1..a7d4b1101b5 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 @@ -13337,6 +13337,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/intN.kt"); } + @TestMetadata("null.kt") + public void testNull() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/null.kt"); + } + @TestMetadata("result.kt") public void testResult() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/result.kt"); 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 f9e2a48e616..ed0648cf9e5 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 @@ -7342,6 +7342,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/intN.kt"); } + @TestMetadata("null.kt") + public void testNull() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/null.kt"); + } + @TestMetadata("result.kt") public void testResult() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/result.kt");