Use TypeSystemCommonBackendContext in computeExpandedTypeForInlineClass

This commit is contained in:
Alexander Udalov
2019-06-21 16:30:40 +02:00
parent c27d9c4546
commit 13bc5f0c47
4 changed files with 55 additions and 20 deletions
@@ -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<ClassifierDescriptor>): KotlinType? {
val classifier = kotlinType.constructor.declarationDescriptor
?: throw AssertionError("Type with a declaration expected: $kotlinType")
private fun TypeSystemCommonBackendContext.computeExpandedTypeInner(
kotlinType: KotlinTypeMarker, visitedClassifiers: HashSet<TypeConstructorMarker>
): 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()
@@ -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 <T : Any> 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,
@@ -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
}
@@ -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 {