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:
pyos
2021-05-10 17:26:47 +02:00
committed by Ilmir Usmanov
parent 614d529168
commit 656c2496a6
13 changed files with 72 additions and 56 deletions
@@ -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 {
@@ -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.
@@ -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
@@ -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)
@@ -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"
@@ -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 {
@@ -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 {
@@ -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");
@@ -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");
@@ -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");
@@ -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");
@@ -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");