Rework nullability in IR

This commit is contained in:
Pavel Kunyavskiy
2022-03-18 13:40:20 +03:00
committed by Space
parent 000165b12b
commit 7ba4d9e1f0
108 changed files with 1679 additions and 469 deletions
@@ -1131,12 +1131,13 @@ private fun getContainingDeclaration(declaration: IrDeclaration): DeclarationDes
fun IrType.toIrBasedKotlinType(): KotlinType = when (this) {
is IrSimpleType ->
makeKotlinType(classifier, arguments, hasQuestionMark)
is IrDefinitelyNotNullType -> {
val kotlinType = this.original.toIrBasedKotlinType()
DefinitelyNotNullType.makeDefinitelyNotNull(kotlinType.unwrap())
?: kotlinType
}
makeKotlinType(classifier, arguments, isMarkedNullable()).let {
if (classifier is IrTypeParameterSymbol && nullability == SimpleTypeNullability.DEFINITELY_NOT_NULL) {
DefinitelyNotNullType.makeDefinitelyNotNull(it.unwrap()) ?: it
} else {
it
}
}
else ->
throw AssertionError("Unexpected type: $this = ${this.render()}")
}
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeBuilder
@@ -186,14 +185,14 @@ class IrBuiltInsOverDescriptors(
val returnIrType = IrSimpleTypeBuilder().run {
classifier = typeParameterSymbol
kotlinType = returnKotlinType
hasQuestionMark = false
nullability = SimpleTypeNullability.DEFINITELY_NOT_NULL
buildSimpleType()
}
val valueIrType = IrSimpleTypeBuilder().run {
classifier = typeParameterSymbol
kotlinType = valueKotlinType
hasQuestionMark = true
nullability = SimpleTypeNullability.MARKED_NULLABLE
buildSimpleType()
}
@@ -232,7 +231,7 @@ class IrBuiltInsOverDescriptors(
val any = builtIns.anyType
override val anyType = any.toIrType()
override val anyClass = builtIns.any.toIrSymbol()
override val anyNType = anyType.withHasQuestionMark(true)
override val anyNType = anyType.makeNullable()
val bool = builtIns.booleanType
override val booleanType = bool.toIrType()
@@ -273,7 +272,7 @@ class IrBuiltInsOverDescriptors(
val nothing = builtIns.nothingType
override val nothingType = nothing.toIrType()
override val nothingClass = builtIns.nothing.toIrSymbol()
override val nothingNType = nothingType.withHasQuestionMark(true)
override val nothingNType = nothingType.makeNullable()
val unit = builtIns.unitType
override val unitType = unit.toIrType()
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.SimpleTypeNullability
import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
@@ -329,7 +330,7 @@ class IrDescriptorBasedFunctionFactory(
return with(IrSimpleTypeBuilder()) {
classifier =
symbolTable.referenceClassifier(kotlinType.constructor.declarationDescriptor ?: error("No classifier for type $kotlinType"))
hasQuestionMark = kotlinType.isMarkedNullable
nullability = SimpleTypeNullability.fromHasQuestionMark(kotlinType.isMarkedNullable)
arguments = kotlinType.arguments.map {
if (it.isStarProjection) IrStarProjectionImpl
else makeTypeProjection(toIrType(it.type), it.projectionKind)
@@ -52,11 +52,7 @@ class DeepCopyIrTreeWithSymbolsForFakeOverrides(typeArguments: Map<IrTypeParamet
return when (val substitutedType = typeArguments[type.classifier]) {
is IrDynamicType -> substitutedType
is IrDefinitelyNotNullType -> substitutedType
is IrSimpleType -> substitutedType.buildSimpleType {
kotlinType = null
hasQuestionMark = type.hasQuestionMark or substitutedType.isMarkedNullable()
}
is IrSimpleType -> substitutedType.mergeNullability(type)
else -> type.buildSimpleType {
kotlinType = null
classifier = symbolRemapper.getReferencedClassifier(type.classifier)
@@ -32,15 +32,56 @@ abstract class IrErrorType(kotlinType: KotlinType?) : IrTypeBase(kotlinType)
abstract class IrDynamicType(kotlinType: KotlinType?) : IrTypeBase(kotlinType), DynamicTypeMarker
abstract class IrDefinitelyNotNullType(kotlinType: KotlinType?) : IrTypeBase(kotlinType), DefinitelyNotNullTypeMarker {
abstract val original: IrType
enum class SimpleTypeNullability {
MARKED_NULLABLE,
NOT_SPECIFIED,
DEFINITELY_NOT_NULL;
companion object {
fun fromHasQuestionMark(hasQuestionMark: Boolean) = if (hasQuestionMark) MARKED_NULLABLE else NOT_SPECIFIED
}
}
abstract class IrSimpleType(kotlinType: KotlinType?) : IrTypeBase(kotlinType), SimpleTypeMarker, TypeArgumentListMarker {
abstract val classifier: IrClassifierSymbol
abstract val hasQuestionMark: Boolean
/**
* If type is explicitly marked as nullable, [nullability] is [SimpleTypeNullability.MARKED_NULLABLE]
*
* If classifier is type parameter, not marked as nullable, but can store null values,
* if corresponding argument would be nullable, [nullability] is [SimpleTypeNullability.NOT_SPECIFIED]
*
* If type can't store null values, [nullability] is [SimpleTypeNullability.DEFINITELY_NOT_NULL]
*
* Direct usages of this property should be avoided in most cases. Use relevant util functions instead.
*
* In most cases one of following is needed:
*
* Use [IrType.isNullable] to check if null value is possible for this type
*
* Use [IrType.isMarkedNullable] to check if type is marked with question mark in code
*
* Use [IrType.mergeNullability] to apply nullability of type parameter to actual type argument in type substitutions
*
* Use [IrType.makeNotNull] or [IrType.makeNullable] to transfer nullability from one type to another
*/
abstract val nullability: SimpleTypeNullability
abstract val arguments: List<IrTypeArgument>
abstract val abbreviation: IrTypeAbbreviation?
/**
* This property was deprecated and replaced with [nullability] property.
*
* Anyway, in most cases one of utils function would be more suitable, than direct usage.
*
* Check [nullability] property documentation for details
*/
@Deprecated(
level = DeprecationLevel.WARNING,
message = "hasQuestionMark has ambiguous meaning. Use isNullable() or isMarkedNullable() instead.",
)
val hasQuestionMark: Boolean
get() = nullability == SimpleTypeNullability.MARKED_NULLABLE
}
interface IrTypeArgument : TypeArgumentMarker {
@@ -43,8 +43,6 @@ abstract class AbstractIrTypeSubstitutor(private val irBuiltIns: IrBuiltIns) : T
arguments = irType.arguments.map { substituteTypeArgument(it) }
buildSimpleType()
}
is IrDefinitelyNotNullType ->
IrDefinitelyNotNullTypeImpl(null, substituteType(irType.original))
is IrDynamicType,
is IrErrorType ->
irType
@@ -28,6 +28,9 @@ import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.types.TypeCheckerState
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.ir.types.makeNotNull as irMakeNotNull
import org.jetbrains.kotlin.ir.types.makeNullable as irMakeNullable
import org.jetbrains.kotlin.ir.types.isMarkedNullable as irIsMarkedNullable
import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.ir.types.isPrimitiveType as irTypePredicates_isPrimitiveType
@@ -71,20 +74,18 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
override fun SimpleTypeMarker.asDefinitelyNotNullType(): DefinitelyNotNullTypeMarker? = null
override fun SimpleTypeMarker.isMarkedNullable(): Boolean = this is IrSimpleType && hasQuestionMark
override fun SimpleTypeMarker.isMarkedNullable(): Boolean = this is IrSimpleType && this.irIsMarkedNullable()
override fun KotlinTypeMarker.isMarkedNullable(): Boolean = this is IrSimpleType && hasQuestionMark
override fun KotlinTypeMarker.isMarkedNullable(): Boolean = this is IrSimpleType && this.irIsMarkedNullable()
override fun SimpleTypeMarker.withNullability(nullable: Boolean): SimpleTypeMarker {
val simpleType = this as IrSimpleType
return if (simpleType.hasQuestionMark == nullable) simpleType
else simpleType.run { IrSimpleTypeImpl(classifier, nullable, arguments, annotations) }
return (if (nullable) simpleType.irMakeNullable() else simpleType.irMakeNotNull()) as IrSimpleType
}
override fun SimpleTypeMarker.typeConstructor(): TypeConstructorMarker = when (this) {
is IrCapturedType -> constructor
is IrSimpleType -> classifier
is IrDefinitelyNotNullType -> original.typeConstructor()
else -> error("Unknown type constructor")
}
@@ -290,7 +291,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
}
}
return IrSimpleTypeImpl(type.classifier, type.hasQuestionMark, newArguments, type.annotations)
return IrSimpleTypeImpl(type.classifier, type.nullability, newArguments, type.annotations)
}
override fun SimpleTypeMarker.asArgumentList() = this as IrSimpleType
@@ -341,7 +342,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
require(ourAnnotations?.size == attributes?.size)
return IrSimpleTypeImpl(
constructor as IrClassifierSymbol,
nullable,
if (nullable) SimpleTypeNullability.MARKED_NULLABLE else SimpleTypeNullability.DEFINITELY_NOT_NULL,
arguments.map { it as IrTypeArgument },
ourAnnotations ?: emptyList()
)
@@ -556,7 +557,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
error("Captured type is unsupported in IR")
override fun DefinitelyNotNullTypeMarker.original(): SimpleTypeMarker =
(this as IrDefinitelyNotNullType).original as IrSimpleType
error("DefinitelyNotNullTypeMarker.original() type is unsupported in IR")
override fun KotlinTypeMarker.makeDefinitelyNotNullOrNotNull(): KotlinTypeMarker {
error("makeDefinitelyNotNullOrNotNull is not supported in IR")
@@ -7,10 +7,7 @@ package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.FqNameEqualityChecker
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.types.AbstractTypeChecker
@@ -37,10 +34,15 @@ fun IrType.isSubtypeOf(superType: IrType, typeSystem: IrTypeSystemContext): Bool
fun IrType.isNullable(): Boolean =
when (this) {
is IrDefinitelyNotNullType -> false
is IrSimpleType -> when (val classifier = classifier) {
is IrClassSymbol -> hasQuestionMark
is IrTypeParameterSymbol -> hasQuestionMark || classifier.owner.superTypes.any(IrType::isNullable)
is IrClassSymbol -> nullability == SimpleTypeNullability.MARKED_NULLABLE
is IrTypeParameterSymbol -> when (nullability) {
SimpleTypeNullability.MARKED_NULLABLE -> true
// here is a bug, there should be .all check (not .any),
// but fixing it is a breaking change, see KT-31545 for details
SimpleTypeNullability.NOT_SPECIFIED -> classifier.owner.superTypes.any(IrType::isNullable)
SimpleTypeNullability.DEFINITELY_NOT_NULL -> false
}
else -> error("Unsupported classifier: $classifier")
}
is IrDynamicType -> true
@@ -73,9 +75,3 @@ fun IrType.toArrayOrPrimitiveArrayType(irBuiltIns: IrBuiltIns): IrType =
} else {
irBuiltIns.arrayClass.typeWith(this)
}
fun IrType.unwrapDefinitelyNotNullType(): IrType =
if (this is IrDefinitelyNotNullType)
this.original.unwrapDefinitelyNotNullType()
else
this
@@ -1,31 +0,0 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.types.impl
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.types.IrDefinitelyNotNullType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance
class IrDefinitelyNotNullTypeImpl(
kotlinType: KotlinType?,
override val original: IrType,
) : IrDefinitelyNotNullType(kotlinType) {
override val annotations: List<IrConstructorCall>
get() = original.annotations
override val variance: Variance
get() = Variance.INVARIANT
override fun equals(other: Any?): Boolean =
other is IrDefinitelyNotNullType &&
this.original == other.original
override fun hashCode(): Int =
original.hashCode()
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.types.impl
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.FqNameEqualityChecker
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance
@@ -18,7 +19,7 @@ abstract class IrAbstractSimpleType(kotlinType: KotlinType?) : IrSimpleType(kotl
get() = Variance.INVARIANT
abstract override val classifier: IrClassifierSymbol
abstract override val hasQuestionMark: Boolean
abstract override val nullability: SimpleTypeNullability
abstract override val arguments: List<IrTypeArgument>
abstract override val annotations: List<IrConstructorCall>
abstract override val abbreviation: IrTypeAbbreviation?
@@ -26,12 +27,12 @@ abstract class IrAbstractSimpleType(kotlinType: KotlinType?) : IrSimpleType(kotl
override fun equals(other: Any?): Boolean =
other is IrAbstractSimpleType &&
FqNameEqualityChecker.areEqual(classifier, other.classifier) &&
hasQuestionMark == other.hasQuestionMark &&
nullability == other.nullability &&
arguments == other.arguments
override fun hashCode(): Int =
(FqNameEqualityChecker.getHashCode(classifier) * 31 +
hasQuestionMark.hashCode()) * 31 +
nullability.hashCode()) * 31 +
arguments.hashCode()
}
@@ -41,8 +42,8 @@ abstract class IrDelegatedSimpleType(kotlinType: KotlinType? = null) : IrAbstrac
override val classifier: IrClassifierSymbol
get() = delegate.classifier
override val hasQuestionMark: Boolean
get() = delegate.hasQuestionMark
override val nullability: SimpleTypeNullability
get() = delegate.nullability
override val arguments: List<IrTypeArgument>
get() = delegate.arguments
override val abbreviation: IrTypeAbbreviation?
@@ -54,25 +55,40 @@ abstract class IrDelegatedSimpleType(kotlinType: KotlinType? = null) : IrAbstrac
class IrSimpleTypeImpl(
kotlinType: KotlinType?,
override val classifier: IrClassifierSymbol,
override val hasQuestionMark: Boolean,
nullability: SimpleTypeNullability,
override val arguments: List<IrTypeArgument>,
override val annotations: List<IrConstructorCall>,
override val abbreviation: IrTypeAbbreviation? = null
) : IrAbstractSimpleType(kotlinType) {
override val nullability =
if (classifier !is IrTypeParameterSymbol && nullability == SimpleTypeNullability.NOT_SPECIFIED)
SimpleTypeNullability.DEFINITELY_NOT_NULL
else
nullability
constructor(
classifier: IrClassifierSymbol,
nullability: SimpleTypeNullability,
arguments: List<IrTypeArgument>,
annotations: List<IrConstructorCall>,
abbreviation: IrTypeAbbreviation? = null
) : this(null, classifier, nullability, arguments, annotations, abbreviation)
constructor(
classifier: IrClassifierSymbol,
hasQuestionMark: Boolean,
arguments: List<IrTypeArgument>,
annotations: List<IrConstructorCall>,
abbreviation: IrTypeAbbreviation? = null
) : this(null, classifier, hasQuestionMark, arguments, annotations, abbreviation)
) : this(null, classifier, SimpleTypeNullability.fromHasQuestionMark(hasQuestionMark), arguments, annotations, abbreviation)
}
class IrSimpleTypeBuilder {
var kotlinType: KotlinType? = null
var classifier: IrClassifierSymbol? = null
var hasQuestionMark = false
var nullability = SimpleTypeNullability.NOT_SPECIFIED
var arguments: List<IrTypeArgument> = emptyList()
var annotations: List<IrConstructorCall> = emptyList()
var abbreviation: IrTypeAbbreviation? = null
@@ -83,7 +99,7 @@ fun IrSimpleType.toBuilder() =
IrSimpleTypeBuilder().also { b ->
b.kotlinType = originalKotlinType
b.classifier = classifier
b.hasQuestionMark = hasQuestionMark
b.nullability = nullability
b.arguments = arguments
b.annotations = annotations
b.abbreviation = abbreviation
@@ -93,7 +109,7 @@ fun IrSimpleTypeBuilder.buildSimpleType() =
IrSimpleTypeImpl(
kotlinType,
classifier ?: throw AssertionError("Classifier not provided"),
hasQuestionMark,
nullability,
arguments,
annotations,
abbreviation
@@ -122,7 +138,6 @@ class IrTypeProjectionImpl internal constructor(
fun makeTypeProjection(type: IrType, variance: Variance): IrTypeProjection =
when {
type is IrCapturedType -> IrTypeProjectionImpl(type, variance)
type is IrDefinitelyNotNullType -> IrTypeProjectionImpl(type, variance)
type is IrTypeProjection && type.variance == variance -> type
type is IrSimpleType -> type.toBuilder().apply { this.variance = variance }.buildTypeProjection()
type is IrDynamicType -> IrDynamicTypeImpl(null, type.annotations, variance)
@@ -103,7 +103,7 @@ class IrCapturedType(
override val classifier: IrClassifierSymbol get() = error("Captured Type does not have a classifier")
override val arguments: List<IrTypeArgument> get() = emptyList()
override val abbreviation: IrTypeAbbreviation? get () = null
override val hasQuestionMark: Boolean get() = false
override val nullability: SimpleTypeNullability get() = SimpleTypeNullability.DEFINITELY_NOT_NULL
override val annotations: List<IrConstructorCall> get() = emptyList()
override fun equals(other: Any?): Boolean {
@@ -48,15 +48,15 @@ object IdSignatureValues {
@JvmField val sequence = IdSignature.CommonSignature("kotlin.sequences", "Sequence", null, 0)
}
private fun IrType.isNotNullClassType(signature: IdSignature.CommonSignature) = isClassType(signature, hasQuestionMark = false)
private fun IrType.isNullableClassType(signature: IdSignature.CommonSignature) = isClassType(signature, hasQuestionMark = true)
private fun IrType.isNotNullClassType(signature: IdSignature.CommonSignature) = isClassType(signature, nullable = false)
private fun IrType.isNullableClassType(signature: IdSignature.CommonSignature) = isClassType(signature, nullable = true)
fun getPublicSignature(packageFqName: FqName, name: String) =
IdSignature.CommonSignature(packageFqName.asString(), name, null, 0)
private fun IrType.isClassType(signature: IdSignature.CommonSignature, hasQuestionMark: Boolean? = null): Boolean {
private fun IrType.isClassType(signature: IdSignature.CommonSignature, nullable: Boolean? = null): Boolean {
if (this !is IrSimpleType) return false
if (hasQuestionMark != null && this.hasQuestionMark != hasQuestionMark) return false
if (nullable != null && this.isMarkedNullable() != nullable) return false
return signature == classifier.signature ||
classifier.owner.let { it is IrClass && it.hasFqNameEqualToSignature(signature) }
}
@@ -109,16 +109,16 @@ fun IrType.isCollection(): Boolean = isNotNullClassType(IdSignatureValues.collec
fun IrType.isNothing(): Boolean = isNotNullClassType(IdSignatureValues.nothing)
fun IrType.isNullableNothing(): Boolean = isNullableClassType(IdSignatureValues.nothing)
fun IrType.isPrimitiveType(hasQuestionMark: Boolean = false): Boolean =
this is IrSimpleType && hasQuestionMark == this.hasQuestionMark && getPrimitiveType() != null
fun IrType.isPrimitiveType(nullable: Boolean = false): Boolean =
nullable == this.isMarkedNullable() && getPrimitiveType() != null
fun IrType.isNullablePrimitiveType(): Boolean = isPrimitiveType(true)
fun IrType.getPrimitiveType(): PrimitiveType? =
getPrimitiveOrUnsignedType(idSignatureToPrimitiveType, shortNameToPrimitiveType)
fun IrType.isUnsignedType(hasQuestionMark: Boolean = false): Boolean =
this is IrSimpleType && hasQuestionMark == this.hasQuestionMark && getUnsignedType() != null
fun IrType.isUnsignedType(nullable: Boolean = false): Boolean =
nullable == this.isMarkedNullable() && getUnsignedType() != null
fun IrType.getUnsignedType(): UnsignedType? =
getPrimitiveOrUnsignedType(idSignatureToUnsignedType, shortNameToUnsignedType)
@@ -134,7 +134,8 @@ fun <T : Enum<T>> IrType.getPrimitiveOrUnsignedType(byIdSignature: Map<IdSignatu
return byShortName[klass.name]
}
fun IrType.isMarkedNullable() = (this as? IrSimpleType)?.hasQuestionMark ?: false
fun IrType.isMarkedNullable() = (this as? IrSimpleType)?.nullability == SimpleTypeNullability.MARKED_NULLABLE
fun IrSimpleType.isMarkedNullable() = nullability == SimpleTypeNullability.MARKED_NULLABLE
fun IrType.isUnit() = isNotNullClassType(IdSignatureValues.unit)
@@ -152,8 +153,8 @@ fun IrType.isFloat(): Boolean = isNotNullClassType(IdSignatureValues._float)
fun IrType.isDouble(): Boolean = isNotNullClassType(IdSignatureValues._double)
fun IrType.isNumber(): Boolean = isNotNullClassType(IdSignatureValues.number)
fun IrType.isDoubleOrFloatWithoutNullability(): Boolean {
return isClassType(IdSignatureValues._double, hasQuestionMark = null) ||
isClassType(IdSignatureValues._float, hasQuestionMark = null)
return isClassType(IdSignatureValues._double, nullable = null) ||
isClassType(IdSignatureValues._float, nullable = null)
}
fun IrType.isComparable(): Boolean = isNotNullClassType(IdSignatureValues.comparable)
@@ -170,9 +171,9 @@ fun IrType.isLongArray(): Boolean = isNotNullClassType(primitiveArrayTypesSignat
fun IrType.isFloatArray(): Boolean = isNotNullClassType(primitiveArrayTypesSignatures[PrimitiveType.FLOAT]!!)
fun IrType.isDoubleArray(): Boolean = isNotNullClassType(primitiveArrayTypesSignatures[PrimitiveType.DOUBLE]!!)
fun IrType.isClassType(fqName: FqNameUnsafe, hasQuestionMark: Boolean): Boolean {
fun IrType.isClassType(fqName: FqNameUnsafe, nullable: Boolean): Boolean {
if (this !is IrSimpleType) return false
if (this.hasQuestionMark != hasQuestionMark) return false
if (this.isMarkedNullable() != nullable) return false
return classifier.isClassWithFqName(fqName)
}
@@ -20,27 +20,29 @@ import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
fun IrType.withHasQuestionMark(newHasQuestionMark: Boolean): IrType =
private fun IrType.withNullability(newNullability: Boolean): IrType =
when (this) {
is IrSimpleType -> withHasQuestionMark(newHasQuestionMark)
is IrSimpleType -> withNullability(newNullability)
else -> this
}
fun IrSimpleType.withHasQuestionMark(newHasQuestionMark: Boolean): IrSimpleType =
if (this.hasQuestionMark == newHasQuestionMark)
private fun IrSimpleType.withNullability(newNullability: Boolean): IrSimpleType {
val requiredNullability = if (newNullability) SimpleTypeNullability.MARKED_NULLABLE else SimpleTypeNullability.DEFINITELY_NOT_NULL
return if (nullability == requiredNullability)
this
else
buildSimpleType {
hasQuestionMark = newHasQuestionMark
nullability = requiredNullability
kotlinType = originalKotlinType?.run {
if (newHasQuestionMark) makeNullable() else makeNotNullable()
if (newNullability) {
TypeUtils.makeNullable(this)
} else {
DefinitelyNotNullType.makeDefinitelyNotNull(this.unwrap()) ?: TypeUtils.makeNotNullable(this)
}
}
}
}
fun IrType.addAnnotations(newAnnotations: List<IrConstructorCall>): IrType =
if (newAnnotations.isEmpty())
@@ -86,7 +88,6 @@ val IrType.classifierOrFail: IrClassifierSymbol
val IrType.classifierOrNull: IrClassifierSymbol?
get() = when (this) {
is IrSimpleType -> classifier
is IrDefinitelyNotNullType -> original.classifierOrNull
else -> null
}
@@ -103,34 +104,18 @@ val IrType.classFqName: FqName?
val IrTypeArgument.typeOrNull: IrType? get() = (this as? IrTypeProjection)?.type
fun IrType.makeNotNull() =
if (this is IrSimpleType && this.hasQuestionMark) {
buildSimpleType {
kotlinType = originalKotlinType?.makeNotNullable()
hasQuestionMark = false
}
} else {
this
}
fun IrType.makeNotNull() = withNullability(false)
fun IrType.makeNullable(): IrType =
when (this) {
is IrSimpleType -> {
if (this.hasQuestionMark)
this
else
buildSimpleType {
kotlinType = originalKotlinType?.makeNullable()
hasQuestionMark = true
}
}
is IrDefinitelyNotNullType -> {
// '{ T & Any }?' => 'T?'
this.original.makeNullable()
}
else ->
this
fun IrType.makeNullable() = withNullability(true)
fun IrType.mergeNullability(other: IrType) = when (other) {
is IrSimpleType -> when (other.nullability) {
SimpleTypeNullability.MARKED_NULLABLE -> makeNullable()
SimpleTypeNullability.NOT_SPECIFIED -> this
SimpleTypeNullability.DEFINITELY_NOT_NULL -> makeNotNull()
}
else -> this
}
@ObsoleteDescriptorBasedAPI
fun IrType.toKotlinType(): KotlinType {
@@ -139,7 +124,7 @@ fun IrType.toKotlinType(): KotlinType {
}
return when (this) {
is IrSimpleType -> makeKotlinType(classifier, arguments, hasQuestionMark)
is IrSimpleType -> makeKotlinType(classifier, arguments, nullability == SimpleTypeNullability.MARKED_NULLABLE)
else -> TODO(toString())
}
}
@@ -181,7 +166,7 @@ val IrClassifierSymbol.defaultType: IrType
val IrTypeParameter.defaultType: IrType
get() = IrSimpleTypeImpl(
symbol,
hasQuestionMark = false,
SimpleTypeNullability.NOT_SPECIFIED,
arguments = emptyList(),
annotations = emptyList()
)
@@ -189,7 +174,7 @@ val IrTypeParameter.defaultType: IrType
val IrClassSymbol.starProjectedType: IrSimpleType
get() = IrSimpleTypeImpl(
this,
hasQuestionMark = false,
SimpleTypeNullability.NOT_SPECIFIED,
arguments = owner.typeConstructorParameters.map { IrStarProjectionImpl }.toList(),
annotations = emptyList()
)
@@ -230,13 +215,13 @@ fun IrClassifierSymbol.typeWith(vararg arguments: IrType): IrSimpleType = typeWi
fun IrClassifierSymbol.typeWith(arguments: List<IrType>): IrSimpleType =
IrSimpleTypeImpl(
this,
false,
SimpleTypeNullability.NOT_SPECIFIED,
arguments.map { makeTypeProjection(it, Variance.INVARIANT) },
emptyList()
)
fun IrClassifierSymbol.typeWithArguments(arguments: List<IrTypeArgument>): IrSimpleType =
IrSimpleTypeImpl(this, false, arguments, emptyList())
IrSimpleTypeImpl(this, SimpleTypeNullability.NOT_SPECIFIED, arguments, emptyList())
fun IrClass.typeWith(arguments: List<IrType>) = this.symbol.typeWith(arguments)
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrDefinitelyNotNullTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrTypeAbbreviationImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
@@ -29,11 +28,10 @@ class DeepCopyTypeRemapper(
override fun remapType(type: IrType): IrType {
return when (type) {
is IrDefinitelyNotNullType -> IrDefinitelyNotNullTypeImpl(null, remapType(type.original))
is IrSimpleType -> IrSimpleTypeImpl(
null,
symbolRemapper.getReferencedClassifier(type.classifier),
type.hasQuestionMark,
type.nullability,
type.arguments.map { remapTypeArgument(it) },
type.annotations.map { it.transform(deepCopy, null) as IrConstructorCall },
type.abbreviation?.remapTypeAbbreviation()
@@ -29,7 +29,7 @@ class IrTypeParameterRemapper(
IrSimpleTypeImpl(
null,
type.classifier.remap(),
type.hasQuestionMark,
type.nullability,
type.arguments.map { it.remap() },
type.annotations,
type.abbreviation?.remap()
@@ -12,10 +12,7 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeAliasSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.ReturnTypeIsNotInitializedException
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
@@ -113,9 +110,9 @@ class RenderIrElementVisitor(private val normalizeNames: Boolean = false, privat
is IrErrorType -> "IrErrorType(${if (verboseErrorTypes) originalKotlinType else null})"
is IrDefinitelyNotNullType -> "{${original.render()} & Any}"
is IrSimpleType -> buildTrimEnd {
val isDefinitelyNotNullType = classifier is IrTypeParameterSymbol && nullability == SimpleTypeNullability.DEFINITELY_NOT_NULL
if (isDefinitelyNotNullType) append("{")
append(classifier.renderClassifierFqn())
if (arguments.isNotEmpty()) {
append(
@@ -124,7 +121,9 @@ class RenderIrElementVisitor(private val normalizeNames: Boolean = false, privat
}
)
}
if (hasQuestionMark) {
if (isDefinitelyNotNullType) {
append(" & Any}")
} else if (isMarkedNullable()) {
append('?')
}
abbreviation?.let {
@@ -33,7 +33,7 @@ class SimpleTypeRemapper(
IrSimpleTypeImpl(
null,
symbol,
type.hasQuestionMark,
type.nullability,
arguments,
type.annotations,
type.abbreviation?.remapTypeAbbreviation()
@@ -17,9 +17,7 @@ import org.jetbrains.kotlin.ir.descriptors.IrBasedTypeParameterDescriptor
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeAbbreviation
import org.jetbrains.kotlin.ir.types.IrTypeProjection
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections
@@ -101,7 +99,7 @@ abstract class TypeTranslator(
approximatedType.isDynamic() ->
return IrDynamicTypeImpl(approximatedType, translateTypeAnnotations(approximatedType), variance)
supportDefinitelyNotNullTypes && approximatedType is DefinitelyNotNullType ->
return makeTypeProjection(IrDefinitelyNotNullTypeImpl(approximatedType, translateType(approximatedType.original)), variance)
return makeTypeProjection(translateType(approximatedType.original).makeNotNull(), variance)
}
val upperType = approximatedType.upperIfFlexible()
@@ -121,7 +119,7 @@ abstract class TypeTranslator(
return IrSimpleTypeBuilder().apply {
this.kotlinType = approximatedType
this.hasQuestionMark = upperType.isMarkedNullable
this.nullability = SimpleTypeNullability.fromHasQuestionMark(upperType.isMarkedNullable)
this.variance = variance
this.abbreviation = upperType.getAbbreviation()?.toIrTypeAbbreviation()
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.Name
@@ -422,14 +423,14 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
// TODO don't print `Any?` as upper bound?
printAnnotationsWithNoIndent()
when (this) {
is IrDefinitelyNotNullType -> {
p.printWithNoIndent("(")
original.printTypeWithNoIndent()
p.printWithNoIndent(" & Any)")
}
is IrSimpleType -> {
// TODO abbreviation
val dnn = classifier is IrTypeParameterSymbol && nullability == SimpleTypeNullability.DEFINITELY_NOT_NULL
if (dnn) {
p.printWithNoIndent("(")
}
p.printWithNoIndent((classifier.owner as IrDeclarationWithName).name.asString())
if (arguments.isNotEmpty()) {
@@ -442,7 +443,11 @@ private class KotlinLikeDumper(val p: Printer, val options: KotlinLikeDumpOption
p.printWithNoIndent(">")
}
if (hasQuestionMark) p.printWithNoIndent("?")
if (dnn) {
p.printWithNoIndent(" & Any)")
}
if (isMarkedNullable()) p.printWithNoIndent("?")
}
is IrDynamicType ->
p.printWithNoIndent("dynamic")