From a7e2f7a6b6e906995f6d2f8c582406070873fc83 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Thu, 30 Dec 2021 16:52:38 +0100 Subject: [PATCH] Map nullable type parameter with nullable inline class upper bound which, in turn, has primitive or nullable underlying type to inline class. #KT-32162 --- .../jetbrains/kotlin/types/AbstractTypeMapper.kt | 7 ++++++- .../inlineClasses/kt27096_primitiveGeneric.kt | 12 ++++++------ .../nullableWrapperEqualityGeneric.kt | 2 +- .../jetbrains/kotlin/types/expandedTypeUtils.kt | 16 ++++++++++------ 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/compiler/backend.common.jvm/src/org/jetbrains/kotlin/types/AbstractTypeMapper.kt b/compiler/backend.common.jvm/src/org/jetbrains/kotlin/types/AbstractTypeMapper.kt index d7abe362c41..390835f36b8 100644 --- a/compiler/backend.common.jvm/src/org/jetbrains/kotlin/types/AbstractTypeMapper.kt +++ b/compiler/backend.common.jvm/src/org/jetbrains/kotlin/types/AbstractTypeMapper.kt @@ -82,7 +82,12 @@ object AbstractTypeMapper { return when { typeConstructor.isTypeParameter() -> { val typeParameter = typeConstructor.asTypeParameter() - val asmType = mapType(context, typeParameter.representativeUpperBound(), mode, null) + val upperBound = typeParameter.representativeUpperBound() + val newType = if (upperBound.typeConstructor().isInlineClass() && type.isNullableType()) + upperBound.makeNullable() + else upperBound + + val asmType = mapType(context, newType, mode, null) sw?.writeTypeVariable(typeParameter.getName(), asmType) asmType } diff --git a/compiler/testData/codegen/box/inlineClasses/kt27096_primitiveGeneric.kt b/compiler/testData/codegen/box/inlineClasses/kt27096_primitiveGeneric.kt index c4ed63b6309..852a0a3fede 100644 --- a/compiler/testData/codegen/box/inlineClasses/kt27096_primitiveGeneric.kt +++ b/compiler/testData/codegen/box/inlineClasses/kt27096_primitiveGeneric.kt @@ -6,13 +6,13 @@ OPTIONAL_JVM_INLINE_ANNOTATION value class Z1(val x: T) OPTIONAL_JVM_INLINE_ANNOTATION -value class Z2>(val z: T) +value class Z2>(val z1: T) OPTIONAL_JVM_INLINE_ANNOTATION -value class ZN>(val z: T?) +value class ZN>(val z1: TN?) OPTIONAL_JVM_INLINE_ANNOTATION -value class ZN2>>(val z: T) +value class ZN2>>(val zn: T) fun wrap1(n: Int): Z1? = if (n < 0) null else Z1(n) fun wrap2(n: Int): Z2>? = if (n < 0) null else Z2(Z1(n)) @@ -26,15 +26,15 @@ fun box(): String { if (wrap2(-1) != null) throw AssertionError() if (wrap2(42) == null) throw AssertionError() - if (wrap2(42)!!.z.x != 42) throw AssertionError() + if (wrap2(42)!!.z1.x != 42) throw AssertionError() if (wrapN(-1) != null) throw AssertionError() if (wrapN(42) == null) throw AssertionError() - if (wrapN(42)!!.z!!.x != 42) throw AssertionError() + if (wrapN(42)!!.z1!!.x != 42) throw AssertionError() if (wrapN2(-1) != null) throw AssertionError() if (wrapN2(42) == null) throw AssertionError() - if (wrapN2(42)!!.z.z!!.x != 42) throw AssertionError() + if (wrapN2(42)!!.zn.z1!!.x != 42) throw AssertionError() return "OK" } \ No newline at end of file diff --git a/compiler/testData/codegen/box/inlineClasses/nullableWrapperEqualityGeneric.kt b/compiler/testData/codegen/box/inlineClasses/nullableWrapperEqualityGeneric.kt index 7ac629e53e1..1bb2a4a6f04 100644 --- a/compiler/testData/codegen/box/inlineClasses/nullableWrapperEqualityGeneric.kt +++ b/compiler/testData/codegen/box/inlineClasses/nullableWrapperEqualityGeneric.kt @@ -9,7 +9,7 @@ OPTIONAL_JVM_INLINE_ANNOTATION value class ZN?>(val z: T) OPTIONAL_JVM_INLINE_ANNOTATION -value class ZN2?>>(val z: T) +value class ZN2?>>(val z: TN) fun zap(b: Boolean): ZN2?>>? = if (b) null else ZN2(ZN(null)) diff --git a/core/compiler.common.jvm/src/org/jetbrains/kotlin/types/expandedTypeUtils.kt b/core/compiler.common.jvm/src/org/jetbrains/kotlin/types/expandedTypeUtils.kt index cca6da89a1e..fad5f158203 100644 --- a/core/compiler.common.jvm/src/org/jetbrains/kotlin/types/expandedTypeUtils.kt +++ b/core/compiler.common.jvm/src/org/jetbrains/kotlin/types/expandedTypeUtils.kt @@ -21,14 +21,18 @@ private fun TypeSystemCommonBackendContext.computeExpandedTypeInner( val typeParameter = classifier.getTypeParameterClassifier() return when { - typeParameter != null -> - computeExpandedTypeInner(typeParameter.getRepresentativeUpperBound(), visitedClassifiers) + typeParameter != null -> { + val upperBound = typeParameter.getRepresentativeUpperBound() + computeExpandedTypeInner(upperBound, visitedClassifiers) ?.let { expandedUpperBound -> - if (expandedUpperBound.isNullableType() || !kotlinType.isMarkedNullable()) - expandedUpperBound - else - expandedUpperBound.makeNullable() + when { + expandedUpperBound is SimpleTypeMarker && expandedUpperBound.isPrimitiveType() && + kotlinType.isNullableType() && upperBound.typeConstructor().isInlineClass() -> upperBound.makeNullable() + expandedUpperBound.isNullableType() || !kotlinType.isMarkedNullable() -> expandedUpperBound + else -> expandedUpperBound.makeNullable() + } } + } classifier.isInlineClass() -> { // kotlinType is the boxed inline class type