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
@@ -80,7 +80,7 @@ private fun JvmIrBuilder.normalizeArgument(expression: IrExpression): IrExpressi
// upcast to 'String?'
return irImplicitCast(expression, context.irBuiltIns.stringType.makeNullable())
}
if (type is IrSimpleType && !type.hasQuestionMark || type is IrDefinitelyNotNullType) {
if (!type.isNullable()) {
if (upperBound.isByte() || upperBound.isShort()) {
// Expression type is not null,
// T <: Byte || T <: Short =>
@@ -548,9 +548,7 @@ internal class LambdaMetafactoryArgumentsBuilder(
)
}
private fun computeParameterTypeAdaptationConstraint(adapteeType0: IrType, expectedType0: IrType): TypeAdaptationConstraint? {
val adapteeType = adapteeType0.unwrapDefinitelyNotNullType()
val expectedType = expectedType0.unwrapDefinitelyNotNullType()
private fun computeParameterTypeAdaptationConstraint(adapteeType: IrType, expectedType: IrType): TypeAdaptationConstraint? {
if (adapteeType !is IrSimpleType)
throw AssertionError("Simple type expected: ${adapteeType.render()}")
if (expectedType !is IrSimpleType)
@@ -582,7 +580,7 @@ internal class LambdaMetafactoryArgumentsBuilder(
// Inline classes mapped to non-null reference types are a special case because they can't be boxed trivially.
// TODO consider adding a special type annotation to force boxing on an inline class type regardless of its underlying type.
val underlyingAdapteeType = getInlineClassUnderlyingType(erasedAdapteeClass)
if (!underlyingAdapteeType.hasQuestionMark && !underlyingAdapteeType.isPrimitiveType()) {
if (!underlyingAdapteeType.isNullable() && !underlyingAdapteeType.isPrimitiveType()) {
return TypeAdaptationConstraint.CONFLICT
}
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
import org.jetbrains.kotlin.ir.types.isMarkedNullable as irIsMarkedNullable
import org.jetbrains.kotlin.types.model.FlexibleTypeMarker
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
@@ -35,5 +36,5 @@ class JvmIrTypeSystemContext(override val irBuiltIns: IrBuiltIns) : IrTypeSystem
}
override fun KotlinTypeMarker.isMarkedNullable(): Boolean =
this is IrSimpleType && !isWithFlexibleNullability() && hasQuestionMark
this is IrSimpleType && !isWithFlexibleNullability() && irIsMarkedNullable()
}
@@ -158,7 +158,7 @@ class MemoizedInlineClassReplacements(
parent = irClass
// We ignore type arguments here, since there is no good way to go from type arguments to types in the IR anyway.
val typeArgument =
IrSimpleTypeImpl(null, irClass.symbol, false, List(irClass.typeParameters.size) { IrStarProjectionImpl }, listOf())
IrSimpleTypeImpl(irClass.symbol, false, List(irClass.typeParameters.size) { IrStarProjectionImpl }, listOf())
addValueParameter {
name = InlineClassDescriptorResolver.SPECIALIZED_EQUALS_FIRST_PARAMETER_NAME
type = typeArgument
@@ -9,12 +9,9 @@ import org.jetbrains.kotlin.backend.jvm.JvmSymbols
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classFqName
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
import org.jetbrains.kotlin.ir.types.removeAnnotations
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.util.render
@@ -35,7 +32,7 @@ private class IrJvmFlexibleTypeImpl(
) : IrJvmFlexibleType {
override val lowerBound: IrSimpleType
get() = irType.buildSimpleType {
if (nullability) hasQuestionMark = false
if (this@IrJvmFlexibleTypeImpl.nullability) nullability = SimpleTypeNullability.NOT_SPECIFIED
// No change in classifier is needed for mutability because type's classifier is set to the lower bound anyway
// (see TypeTranslator.translateType).
kotlinType = null
@@ -43,7 +40,7 @@ private class IrJvmFlexibleTypeImpl(
override val upperBound: IrSimpleType
get() = irType.buildSimpleType {
if (nullability) hasQuestionMark = true
if (this@IrJvmFlexibleTypeImpl.nullability) nullability = SimpleTypeNullability.MARKED_NULLABLE
if (mutability) {
val klass = classifier?.owner as? IrClass
?: error("Mutability-flexible type's classifier is not a class: ${irType.render()}")
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.isLocal
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -41,9 +40,9 @@ fun IrType.eraseTypeParameters(): IrType = when (this) {
when (val owner = classifier.owner) {
is IrScript -> {
assert(arguments.isEmpty()) { "Script can't be generic: " + owner.render() }
IrSimpleTypeImpl(classifier, hasQuestionMark, emptyList(), annotations)
IrSimpleTypeImpl(classifier, nullability, emptyList(), annotations)
}
is IrClass -> IrSimpleTypeImpl(classifier, hasQuestionMark, arguments.map { it.eraseTypeParameters() }, annotations)
is IrClass -> IrSimpleTypeImpl(classifier, nullability, arguments.map { it.eraseTypeParameters() }, annotations)
is IrTypeParameter -> {
val upperBound = owner.erasedUpperBound
IrSimpleTypeImpl(
@@ -56,8 +55,6 @@ fun IrType.eraseTypeParameters(): IrType = when (this) {
}
else -> error("Unknown IrSimpleType classifier kind: $owner")
}
is IrDefinitelyNotNullType ->
this.original.eraseTypeParameters()
is IrErrorType ->
this
else -> error("Unknown IrType kind: $this")
@@ -88,15 +85,12 @@ val IrTypeParameter.erasedUpperBound: IrClass
val IrType.erasedUpperBound: IrClass
get() =
if (this is IrDefinitelyNotNullType)
this.original.erasedUpperBound
else
when (val classifier = classifierOrNull) {
is IrClassSymbol -> classifier.owner
is IrTypeParameterSymbol -> classifier.owner.erasedUpperBound
is IrScriptSymbol -> classifier.owner.targetClass!!.owner
else -> error(render())
}
when (val classifier = classifierOrNull) {
is IrClassSymbol -> classifier.owner
is IrTypeParameterSymbol -> classifier.owner.erasedUpperBound
is IrScriptSymbol -> classifier.owner.targetClass!!.owner
else -> error(render())
}
/**
* Get the default null/0 value for the type.
@@ -111,7 +105,7 @@ fun IrType.defaultValue(startOffset: Int, endOffset: Int, context: JvmBackendCon
return classifier.owner.representativeUpperBound.defaultValue(startOffset, endOffset, context)
}
if (this !is IrSimpleType || hasQuestionMark || classOrNull?.owner?.isSingleFieldValueClass != true)
if (this !is IrSimpleType || this.isMarkedNullable() || classOrNull?.owner?.isSingleFieldValueClass != true)
return IrConstImpl.defaultValueForType(startOffset, endOffset, this)
val underlyingType = unboxInlineClass()
@@ -137,13 +131,13 @@ fun IrType.eraseToScope(visibleTypeParameters: Set<IrTypeParameter>): IrType {
return when (classifier) {
is IrClassSymbol ->
IrSimpleTypeImpl(
classifier, hasQuestionMark, arguments.map { it.eraseToScope(visibleTypeParameters) }, annotations
classifier, nullability, arguments.map { it.eraseToScope(visibleTypeParameters) }, annotations
)
is IrTypeParameterSymbol ->
if (classifier.owner in visibleTypeParameters)
this
else
upperBound.withHasQuestionMark(this.hasQuestionMark)
upperBound.mergeNullability(this)
else -> error("unknown IrType classifier kind: ${classifier.owner.render()}")
}
}