diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java index 933d3031a35..08810f96a64 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java @@ -23485,6 +23485,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr runTest("compiler/testData/codegen/box/inlineClasses/noReturnTypeManglingJvmNameGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); } + @Test + @TestMetadata("nonImmediateInlineClassUpperBound.kt") + public void testNonImmediateInlineClassUpperBound() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/nonImmediateInlineClassUpperBound.kt"); + } + @Test @TestMetadata("nullableEqeqNonNull.kt") public void testNullableEqeqNonNull() throws Exception { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java index 037082a4011..8ad2ddf90ed 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java @@ -23485,6 +23485,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo runTest("compiler/testData/codegen/box/inlineClasses/noReturnTypeManglingJvmNameGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); } + @Test + @TestMetadata("nonImmediateInlineClassUpperBound.kt") + public void testNonImmediateInlineClassUpperBound() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/nonImmediateInlineClassUpperBound.kt"); + } + @Test @TestMetadata("nullableEqeqNonNull.kt") public void testNullableEqeqNonNull() throws Exception { diff --git a/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt b/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt index f99ab3bcf05..8b314aba104 100644 --- a/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt +++ b/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.codegen import org.jetbrains.kotlin.backend.jvm.InlineClassAbi import org.jetbrains.kotlin.backend.jvm.inlineClassFieldName -import org.jetbrains.kotlin.backend.jvm.ir.eraseTypeParameters +import org.jetbrains.kotlin.backend.jvm.ir.eraseIfTypeParameter import org.jetbrains.kotlin.backend.jvm.mapping.IrTypeMapper import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.StackValue @@ -29,8 +29,8 @@ abstract class PromisedValue(val codegen: ExpressionCodegen, val type: Type, val // If this value is immaterial, construct an object on the top of the stack. This // must always be done before generating other values or emitting raw bytecode. open fun materializeAt(target: Type, irTarget: IrType, castForReified: Boolean) { - val erasedSourceType = irType.eraseTypeParameters() - val erasedTargetType = irTarget.eraseTypeParameters() + val erasedSourceType = irType.eraseIfTypeParameter() + val erasedTargetType = irTarget.eraseIfTypeParameter() // Coerce inline classes val isFromTypeUnboxed = InlineClassAbi.unboxType(erasedSourceType)?.let(typeMapper::mapType) == type diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrTypeUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrTypeUtils.kt index a2a6b8cb03b..17b75ea5c4c 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrTypeUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrTypeUtils.kt @@ -44,16 +44,7 @@ fun IrType.eraseTypeParameters(): IrType = when (this) { IrSimpleTypeImpl(classifier, nullability, emptyList(), annotations) } is IrClass -> IrSimpleTypeImpl(classifier, nullability, arguments.map { it.eraseTypeParameters() }, annotations) - is IrTypeParameter -> { - val upperBound = owner.erasedUpperBound - IrSimpleTypeImpl( - upperBound.symbol, - isNullable(), - // Should not affect JVM signature, but may result in an invalid type object - List(upperBound.typeParameters.size) { IrStarProjectionImpl }, - owner.annotations - ) - } + is IrTypeParameter -> owner.erasedType(isNullable()) else -> error("Unknown IrSimpleType classifier kind: $owner") } is IrErrorType -> @@ -61,6 +52,22 @@ fun IrType.eraseTypeParameters(): IrType = when (this) { else -> error("Unknown IrType kind: $this") } +fun IrType.eraseIfTypeParameter(): IrType { + val typeParameter = (this as? IrSimpleType)?.classifier?.owner as? IrTypeParameter ?: return this + return typeParameter.erasedType(isNullable()) +} + +private fun IrTypeParameter.erasedType(isNullable: Boolean): IrType { + val upperBound = erasedUpperBound + return IrSimpleTypeImpl( + upperBound.symbol, + isNullable, + // Should not affect JVM signature, but may result in an invalid type object + List(upperBound.typeParameters.size) { IrStarProjectionImpl }, + annotations + ) +} + private fun IrTypeArgument.eraseTypeParameters(): IrTypeArgument = when (this) { is IrStarProjection -> this is IrTypeProjection -> makeTypeProjection(type.eraseTypeParameters(), variance) diff --git a/compiler/testData/codegen/box/inlineClasses/nonImmediateInlineClassUpperBound.kt b/compiler/testData/codegen/box/inlineClasses/nonImmediateInlineClassUpperBound.kt new file mode 100644 index 00000000000..718379ac075 --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/nonImmediateInlineClassUpperBound.kt @@ -0,0 +1,9 @@ +// TARGET_BACKEND: JVM_IR +// WITH_STDLIB + +@JvmInline +value class Z(val value: String) + +fun foo(t: T) = t.value + +fun box() = foo(Z("OK")) 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 292915f39e5..cbcafe19d05 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 @@ -23485,6 +23485,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inlineClasses/noReturnTypeManglingJvmNameGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); } + @Test + @TestMetadata("nonImmediateInlineClassUpperBound.kt") + public void testNonImmediateInlineClassUpperBound() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/nonImmediateInlineClassUpperBound.kt"); + } + @Test @TestMetadata("nullableEqeqNonNull.kt") public void testNullableEqeqNonNull() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java index bd3fd4d7428..4bff5ae6538 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java @@ -23485,6 +23485,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack runTest("compiler/testData/codegen/box/inlineClasses/noReturnTypeManglingJvmNameGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); } + @Test + @TestMetadata("nonImmediateInlineClassUpperBound.kt") + public void testNonImmediateInlineClassUpperBound() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/nonImmediateInlineClassUpperBound.kt"); + } + @Test @TestMetadata("nullableEqeqNonNull.kt") public void testNullableEqeqNonNull() 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 a8278e935db..5254844ef2f 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -19618,6 +19618,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inlineClasses/noReturnTypeManglingJvmNameGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); } + @TestMetadata("nonImmediateInlineClassUpperBound.kt") + public void testNonImmediateInlineClassUpperBound() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/nonImmediateInlineClassUpperBound.kt"); + } + @TestMetadata("nullableEqeqNonNull.kt") public void testNullableEqeqNonNull() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/nullableEqeqNonNull.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());