diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/inlineClassMapping.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/inlineClassMapping.kt index 382308fda46..1f8509d299b 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/inlineClassMapping.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/inlineClassMapping.kt @@ -6,15 +6,15 @@ package org.jetbrains.kotlin.load.kotlin import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.resolve.substitutedUnderlyingType import org.jetbrains.kotlin.resolve.unsubstitutedUnderlyingType import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.types.isNullable -import org.jetbrains.kotlin.types.typeUtil.makeNullable +import org.jetbrains.kotlin.types.model.KotlinTypeMarker +import org.jetbrains.kotlin.types.model.SimpleTypeMarker +import org.jetbrains.kotlin.types.model.TypeConstructorMarker import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound internal fun computeUnderlyingType(inlineClassType: KotlinType): KotlinType? { @@ -27,39 +27,42 @@ internal fun computeUnderlyingType(inlineClassType: KotlinType): KotlinType? { inlineClassType.substitutedUnderlyingType() } -internal fun computeExpandedTypeForInlineClass(inlineClassType: KotlinType): KotlinType? = +fun TypeSystemCommonBackendContext.computeExpandedTypeForInlineClass(inlineClassType: KotlinTypeMarker): KotlinTypeMarker? = computeExpandedTypeInner(inlineClassType, hashSetOf()) -private fun computeExpandedTypeInner(kotlinType: KotlinType, visitedClassifiers: HashSet): KotlinType? { - val classifier = kotlinType.constructor.declarationDescriptor - ?: throw AssertionError("Type with a declaration expected: $kotlinType") +private fun TypeSystemCommonBackendContext.computeExpandedTypeInner( + kotlinType: KotlinTypeMarker, visitedClassifiers: HashSet +): KotlinTypeMarker? { + val classifier = kotlinType.typeConstructor() if (!visitedClassifiers.add(classifier)) return null + val typeParameter = classifier.getTypeParameterClassifier() + return when { - classifier is TypeParameterDescriptor -> - computeExpandedTypeInner(classifier.representativeUpperBound, visitedClassifiers) + typeParameter != null -> + computeExpandedTypeInner(typeParameter.getRepresentativeUpperBound(), visitedClassifiers) ?.let { expandedUpperBound -> - if (expandedUpperBound.isNullable() || !kotlinType.isMarkedNullable) + if (expandedUpperBound.isNullableType() || !kotlinType.isMarkedNullable()) expandedUpperBound else expandedUpperBound.makeNullable() } - classifier is ClassDescriptor && classifier.isInline -> { + classifier.isInlineClass() -> { // kotlinType is the boxed inline class type - val underlyingType = kotlinType.substitutedUnderlyingType() ?: return null + val underlyingType = kotlinType.getSubstitutedUnderlyingType() ?: return null val expandedUnderlyingType = computeExpandedTypeInner(underlyingType, visitedClassifiers) ?: return null when { - !kotlinType.isNullable() -> expandedUnderlyingType + !kotlinType.isNullableType() -> expandedUnderlyingType // Here inline class type is nullable. Apply nullability to the expandedUnderlyingType. // Nullable types become inline class boxes - expandedUnderlyingType.isNullable() -> kotlinType + expandedUnderlyingType.isNullableType() -> kotlinType // Primitives become inline class boxes - KotlinBuiltIns.isPrimitiveType(expandedUnderlyingType) -> kotlinType + expandedUnderlyingType is SimpleTypeMarker && expandedUnderlyingType.isPrimitiveType() -> kotlinType // Non-null reference types become nullable reference types else -> expandedUnderlyingType.makeNullable() diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt index 4d2aef07e83..532e0a676e9 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound import org.jetbrains.kotlin.utils.DO_NOTHING_3 @@ -136,7 +137,7 @@ fun mapType( descriptor is ClassDescriptor -> { // NB if inline class is recursive, it's ok to map it as wrapped if (descriptor.isInline && !mode.needInlineClassWrapping) { - val expandedType = computeExpandedTypeForInlineClass(kotlinType) + val expandedType = SimpleClassicTypeSystemContext.computeExpandedTypeForInlineClass(kotlinType) as KotlinType? if (expandedType != null) { return mapType( expandedType, diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSystemCommonBackendContext.kt b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSystemCommonBackendContext.kt index d432711796f..4ce26d7c58c 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSystemCommonBackendContext.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSystemCommonBackendContext.kt @@ -6,9 +6,7 @@ package org.jetbrains.kotlin.types import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.types.model.KotlinTypeMarker -import org.jetbrains.kotlin.types.model.TypeConstructorMarker -import org.jetbrains.kotlin.types.model.TypeSystemContext +import org.jetbrains.kotlin.types.model.* interface TypeSystemCommonBackendContext : TypeSystemContext { fun TypeConstructorMarker.isFinalClassOrEnumEntryOrAnnotationClassConstructor(): Boolean @@ -24,4 +22,15 @@ interface TypeSystemCommonBackendContext : TypeSystemContext { * TODO: provide a more granular & elaborate API here to reduce confusion */ fun KotlinTypeMarker.getAnnotationFirstArgumentValue(fqName: FqName): Any? + + fun TypeConstructorMarker.getTypeParameterClassifier(): TypeParameterMarker? + fun TypeConstructorMarker.isInlineClass(): Boolean + fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker + fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? + + fun KotlinTypeMarker.isMarkedNullable(): Boolean = + this is SimpleTypeMarker && isMarkedNullable() + + fun KotlinTypeMarker.makeNullable(): KotlinTypeMarker = + asSimpleType()?.withNullability(true) ?: this } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt index ab8b9d2dfe6..ff2d68fcb8f 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt @@ -16,10 +16,12 @@ import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor import org.jetbrains.kotlin.resolve.descriptorUtil.hasExactAnnotation import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation import org.jetbrains.kotlin.resolve.descriptorUtil.isExactAnnotation +import org.jetbrains.kotlin.resolve.substitutedUnderlyingType import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.model.* import org.jetbrains.kotlin.types.typeUtil.asTypeProjection import org.jetbrains.kotlin.types.typeUtil.contains +import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract @@ -495,6 +497,26 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy require(this is KotlinType, this::errorMessage) return annotations.findAnnotation(fqName)?.allValueArguments?.values?.firstOrNull()?.value } + + override fun TypeConstructorMarker.getTypeParameterClassifier(): TypeParameterMarker? { + require(this is TypeConstructor, this::errorMessage) + return declarationDescriptor as? TypeParameterDescriptor + } + + override fun TypeConstructorMarker.isInlineClass(): Boolean { + require(this is TypeConstructor, this::errorMessage) + return (declarationDescriptor as? ClassDescriptor)?.isInline == true + } + + override fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker { + require(this is TypeParameterDescriptor, this::errorMessage) + return representativeUpperBound + } + + override fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? { + require(this is KotlinType, this::errorMessage) + return substitutedUnderlyingType() + } } fun TypeVariance.convertVariance(): Variance {