JVM_IR: omit bound receiver in IrExpressionLambdaImpl parameters
and remove a hack intended to replace the missing type conversions this caused. #KT-46505 Fixed
This commit is contained in:
+6
@@ -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 {
|
||||
|
||||
-15
@@ -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.
|
||||
|
||||
+17
-14
@@ -201,27 +201,30 @@ class IrExpressionLambdaImpl(
|
||||
|
||||
private val loweredMethod = codegen.methodSignatureMapper.mapAsmMethod(function)
|
||||
|
||||
val capturedParamsInDesc: List<Type> = when {
|
||||
isBoundCallableReference -> loweredMethod.argumentTypes.take(1)
|
||||
isExtensionLambda -> loweredMethod.argumentTypes.drop(1).take(capturedVars.size)
|
||||
else -> loweredMethod.argumentTypes.take(capturedVars.size)
|
||||
}
|
||||
private val captureParameterIndices: Pair<Int, Int>
|
||||
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<Type> =
|
||||
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<KotlinType?>
|
||||
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
|
||||
|
||||
|
||||
+7
-19
@@ -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)
|
||||
|
||||
-8
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
Generated
+5
@@ -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");
|
||||
|
||||
Generated
+5
@@ -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");
|
||||
|
||||
Generated
+5
@@ -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");
|
||||
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java
Generated
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user