From 74791495d726999405fd8c96722421163ddd6233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Sch=C3=A4fer?= Date: Wed, 8 Apr 2020 16:09:05 +0200 Subject: [PATCH] JVM IR: Box inline classes in covariant overrides (KT-30419) --- .../jvm/codegen/MethodSignatureMapper.kt | 10 ++++----- .../backend/jvm/lower/BridgeLowering.kt | 21 +++++++++++++++---- .../boxReturnValueInLambda/boxAny.kt | 1 - .../boxFunLiteralAny.kt | 1 - .../boxReturnValueInLambda/boxNullableAny.kt | 1 - .../boxNullableAnyNull.kt | 1 - .../boxReturnValueInLambda/kt27586_1.kt | 1 - .../boxReturnValueInLambda/kt27586_2.kt | 1 - .../covariantOverrideChainErasedToAny.kt | 1 - ...variantOverrideChainErasedToNullableAny.kt | 1 - .../covariantOverrideErasedToAny.kt | 1 - .../covariantOverrideErasedToInterface.kt | 1 - .../covariantOverrideListVsMutableList.kt | 1 - .../genericOverride.kt | 1 - .../boxReturnValueOnOverride/kt28483.kt | 1 - .../relatedReturnTypes1a.kt | 1 - .../relatedReturnTypes1b.kt | 1 - .../callableReferences/kt37986.kt | 3 --- 18 files changed, 21 insertions(+), 28 deletions(-) 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 74e28c6e7fe52..4ca8e89edb64e 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 @@ -182,8 +182,8 @@ class MethodSignatureMapper(private val context: JvmBackendContext) { private fun forceBoxedReturnType(function: IrFunction): Boolean { if (isBoxMethodForInlineClass(function)) return true - return isJvmPrimitive(function.returnType) && - function is IrSimpleFunction && function.allOverridden().any { !isJvmPrimitive(it.returnType) } + return isJvmPrimitiveOrInlineClass(function.returnType) && + function is IrSimpleFunction && function.allOverridden().any { !isJvmPrimitiveOrInlineClass(it.returnType) } } private fun isBoxMethodForInlineClass(function: IrFunction): Boolean = @@ -191,10 +191,8 @@ class MethodSignatureMapper(private val context: JvmBackendContext) { function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_INLINE_CLASS_MEMBER && function.name.asString() == "box-impl" - private fun isJvmPrimitive(type: IrType): Boolean { - if (type.isPrimitiveType()) return true - return type.getClass()?.isInline == true && AsmUtil.isPrimitive(typeMapper.mapType(type)) - } + private fun isJvmPrimitiveOrInlineClass(type: IrType): Boolean = + type.isPrimitiveType() || type.getClass()?.isInline == true fun mapSignatureSkipGeneric(function: IrFunction): JvmMethodSignature = mapSignature(function, true) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt index 1af4839c0dbdd..e8fc66c1d8c4c 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt @@ -15,7 +15,9 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface import org.jetbrains.kotlin.backend.jvm.ir.eraseTypeParameters +import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound import org.jetbrains.kotlin.backend.jvm.ir.isJvmAbstract +import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities @@ -31,6 +33,7 @@ import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.util.OperatorNameConventions +import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.getOrPutNullable import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.Method @@ -172,8 +175,10 @@ private class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass, createBridges(declaration, member) // For lambda classes, we move overrides from the `invoke` function to its bridge. This will allow us to avoid boxing - // the return type of `invoke` in codegen for lambdas with primitive return type. - if (member.name == OperatorNameConventions.INVOKE && declaration.origin == JvmLoweredDeclarationOrigin.LAMBDA_IMPL) { + // the return type of `invoke` in codegen for lambdas with primitive return type. This does not apply to lambdas returning + // inline class types erasing to Any, which we need to box. + if (member.name == OperatorNameConventions.INVOKE && declaration.origin == JvmLoweredDeclarationOrigin.LAMBDA_IMPL + && !member.returnType.isInlineClassErasingToAny) { member.overriddenSymbols = listOf() } } @@ -354,10 +359,15 @@ private class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass, copyParametersWithErasure(this@addBridge, bridge.overridden) body = context.createIrBuilder(symbol).run { irExprBody(delegatingCall(this@apply, target)) } - val redundantOverrides = bridge.overriddenSymbols.flatMapTo(mutableSetOf()) { + // The generated bridge method overrides all of the symbols which were overridden by its overrides. + // This is technically wrong, but it's necessary to generate a method which maps to the same signature. + val inheritedOverrides = bridge.overriddenSymbols.flatMapTo(mutableSetOf()) { function -> + function.owner.safeAs()?.overriddenSymbols ?: emptyList() + } + val redundantOverrides = inheritedOverrides.flatMapTo(mutableSetOf()) { it.owner.allOverridden().map { override -> override.symbol }.asIterable() } - overriddenSymbols = bridge.overriddenSymbols.filter { it !in redundantOverrides } + overriddenSymbols = inheritedOverrides.filter { it !in redundantOverrides } } private fun IrClass.addSpecialBridge(specialBridge: SpecialBridge, target: IrSimpleFunction): IrSimpleFunction = @@ -492,3 +502,6 @@ private fun IrSimpleFunction.resolvesToClass(): Boolean { private fun IrSimpleFunction.overriddenFromClass(): IrSimpleFunction? = overriddenSymbols.singleOrNull { !it.owner.parentAsClass.isJvmInterface }?.owner + +private val IrType.isInlineClassErasingToAny: Boolean + get() = unboxInlineClass().let { unboxed -> unboxed != this && (unboxed.isAny() || unboxed.isNullableAny()) } diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/boxAny.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/boxAny.kt index 98da30bce635a..af13a53113b85 100644 --- a/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/boxAny.kt +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/boxAny.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR inline class X(val x: Any) diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/boxFunLiteralAny.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/boxFunLiteralAny.kt index 2a0155faac3e9..e3a08b28553c4 100644 --- a/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/boxFunLiteralAny.kt +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/boxFunLiteralAny.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR inline class X(val x: Any) diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/boxNullableAny.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/boxNullableAny.kt index 2b28c2cb044e8..98aeb72f9e351 100644 --- a/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/boxNullableAny.kt +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/boxNullableAny.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR inline class X(val x: Any?) diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/boxNullableAnyNull.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/boxNullableAnyNull.kt index 172fe59dc94d6..e7bd2002a10ce 100644 --- a/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/boxNullableAnyNull.kt +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/boxNullableAnyNull.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR inline class X(val x: Any?) diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/kt27586_1.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/kt27586_1.kt index 9ccefe346363d..9e509a053c484 100644 --- a/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/kt27586_1.kt +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/kt27586_1.kt @@ -1,6 +1,5 @@ // WITH_RUNTIME // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR fun f1(): () -> Result { return { diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/kt27586_2.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/kt27586_2.kt index ca519b3acefba..4577ddc2815e4 100644 --- a/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/kt27586_2.kt +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueInLambda/kt27586_2.kt @@ -1,6 +1,5 @@ // WITH_RUNTIME // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR fun f1() = lazy { runCatching { diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideChainErasedToAny.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideChainErasedToAny.kt index 9b20b57e240c8..a2eb019d168d0 100644 --- a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideChainErasedToAny.kt +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideChainErasedToAny.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR inline class X(val x: Any) diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideChainErasedToNullableAny.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideChainErasedToNullableAny.kt index 5cd96164b7a45..51b357544121d 100644 --- a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideChainErasedToNullableAny.kt +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideChainErasedToNullableAny.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR inline class X(val x: Any?) diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideErasedToAny.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideErasedToAny.kt index e96b18124d4c3..27912e1a5af72 100644 --- a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideErasedToAny.kt +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideErasedToAny.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR inline class X(val x: Any) diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideErasedToInterface.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideErasedToInterface.kt index 83dc583fa2514..40db2f74720f6 100644 --- a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideErasedToInterface.kt +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideErasedToInterface.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR interface IFoo { fun foo(): String diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideListVsMutableList.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideListVsMutableList.kt index 0df5bf3189d53..214dfab7357f8 100644 --- a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideListVsMutableList.kt +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideListVsMutableList.kt @@ -1,7 +1,6 @@ // IGNORE_BACKEND_FIR: JVM_IR // WITH_RUNTIME // KJS_WITH_FULL_RUNTIME -// IGNORE_BACKEND: JVM_IR interface IFooList { fun foo(): List diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/genericOverride.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/genericOverride.kt index 5604ec19755de..d8cf4b3bf6d7d 100644 --- a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/genericOverride.kt +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/genericOverride.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR inline class X(val x: Any) diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt28483.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt28483.kt index ba01c3e6672c1..f427b769ed8cf 100644 --- a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt28483.kt +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt28483.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR inline class ResultOrClosed(val x: Any?) diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes1a.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes1a.kt index d47b8d1a396ba..f1886272c01ef 100644 --- a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes1a.kt +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes1a.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR interface IQ { fun ok(): String diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes1b.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes1b.kt index 142781298fb23..1e2110dffac5e 100644 --- a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes1b.kt +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes1b.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR interface IQ { fun ok(): String diff --git a/compiler/testData/codegen/box/inlineClasses/callableReferences/kt37986.kt b/compiler/testData/codegen/box/inlineClasses/callableReferences/kt37986.kt index c71208658b1e4..6a4bd69be76e2 100644 --- a/compiler/testData/codegen/box/inlineClasses/callableReferences/kt37986.kt +++ b/compiler/testData/codegen/box/inlineClasses/callableReferences/kt37986.kt @@ -1,6 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_FIR: JVM_IR - inline class R(val x: Any) fun useR(r: R) {