IR: minor refactorings around IrType/IrCapturedType

- use identity in equals/hashCode. It was already effectively working
  like this because of `constructor === other.constructor`
- implement variance and declare it in IrSimpleType
- remove obsolete TODO
- simplify code in captureFromArguments
- use data objects
This commit is contained in:
Alexander Udalov
2023-11-14 14:48:37 +01:00
committed by Space Team
parent dec41e8c46
commit 898d3aeea9
6 changed files with 37 additions and 67 deletions
@@ -91,6 +91,9 @@ abstract class IrSimpleType(kotlinType: KotlinType?) : IrTypeBase(kotlinType), S
) )
val hasQuestionMark: Boolean val hasQuestionMark: Boolean
get() = nullability == SimpleTypeNullability.MARKED_NULLABLE get() = nullability == SimpleTypeNullability.MARKED_NULLABLE
override val variance: Variance
get() = Variance.INVARIANT
} }
/** /**
@@ -90,7 +90,7 @@ class IrTypeSubstitutor(
override fun isEmptySubstitution(): Boolean = substitution.isEmpty() override fun isEmptySubstitution(): Boolean = substitution.isEmpty()
} }
class IrCapturedTypeSubstitutor( internal class IrCapturedTypeSubstitutor(
typeParameters: List<IrTypeParameterSymbol>, typeParameters: List<IrTypeParameterSymbol>,
typeArguments: List<IrTypeArgument>, typeArguments: List<IrTypeArgument>,
capturedTypes: List<IrCapturedType?>, capturedTypes: List<IrCapturedType?>,
@@ -239,9 +239,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
* *
* See https://kotlinlang.org/spec/type-system.html#type-capturing * See https://kotlinlang.org/spec/type-system.html#type-capturing
*/ */
override fun captureFromArguments(type: SimpleTypeMarker, status: CaptureStatus): SimpleTypeMarker? { override fun captureFromArguments(type: SimpleTypeMarker, status: CaptureStatus): SimpleTypeMarker? {
// TODO: is that correct?
require(type is IrSimpleType) require(type is IrSimpleType)
if (type is IrCapturedType) return null if (type is IrCapturedType) return null
@@ -252,43 +250,33 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
if (!classifier.isBound) return null if (!classifier.isBound) return null
val typeParameters = extractTypeParameters(classifier.owner) val typeParameters = extractTypeParameters(classifier.owner)
require(typeArguments.size == typeParameters.size) require(typeArguments.size == typeParameters.size)
if (typeArguments.all { it is IrTypeProjection && it.variance == Variance.INVARIANT }) return type if (typeArguments.all { it is IrTypeProjection && it.variance == Variance.INVARIANT }) return type
val capturedTypes = ArrayList<IrCapturedType?>(typeArguments.size) val capturedTypes = typeArguments.mapIndexed { index, argument ->
for (index in typeArguments.indices) {
val parameter = typeParameters[index]
val argument = typeArguments[index]
if (argument is IrTypeProjection && argument.variance == Variance.INVARIANT) { if (argument is IrTypeProjection && argument.variance == Variance.INVARIANT) {
capturedTypes.add(null) null
} else { } else {
val lowerType = if (argument is IrTypeProjection && argument.variance == Variance.IN_VARIANCE) { val lowerType = if (argument is IrTypeProjection && argument.variance == Variance.IN_VARIANCE) {
argument.type argument.type
} else null } else null
capturedTypes.add(IrCapturedType(status, lowerType, argument, parameter)) IrCapturedType(status, lowerType, argument, typeParameters[index])
} }
} }
val newArguments = ArrayList<IrTypeArgument>(typeArguments.size)
val typeSubstitutor = IrCapturedTypeSubstitutor(typeParameters.memoryOptimizedMap { it.symbol }, typeArguments, capturedTypes) val typeSubstitutor = IrCapturedTypeSubstitutor(typeParameters.memoryOptimizedMap { it.symbol }, typeArguments, capturedTypes)
for (index in typeArguments.indices) { val newArguments = typeArguments.mapIndexed { index, oldArgument ->
val oldArgument = typeArguments[index]
val parameter = typeParameters[index]
val capturedType = capturedTypes[index] val capturedType = capturedTypes[index]
if (capturedType == null) { if (capturedType == null) {
assert(oldArgument is IrTypeProjection && oldArgument.variance == Variance.INVARIANT) assert(oldArgument is IrTypeProjection && oldArgument.variance == Variance.INVARIANT)
newArguments.add(oldArgument) oldArgument
} else { } else {
val capturedSuperTypes = mutableListOf<IrType>() val capturedSuperTypes = mutableListOf<IrType>()
parameter.superTypes.mapTo(capturedSuperTypes) { typeParameters[index].superTypes.mapTo(capturedSuperTypes) {
typeSubstitutor.substitute(it) typeSubstitutor.substitute(it)
} }
@@ -298,7 +286,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
capturedType.constructor.initSuperTypes(capturedSuperTypes) capturedType.constructor.initSuperTypes(capturedSuperTypes)
newArguments.add(makeTypeProjection(capturedType, Variance.INVARIANT)) makeTypeProjection(capturedType, Variance.INVARIANT)
} }
} }
@@ -10,15 +10,11 @@ import org.jetbrains.kotlin.ir.symbols.FqNameEqualityChecker
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.utils.compactIfPossible
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.compactIfPossible
abstract class IrAbstractSimpleType(kotlinType: KotlinType?) : IrSimpleType(kotlinType) { abstract class IrAbstractSimpleType(kotlinType: KotlinType?) : IrSimpleType(kotlinType) {
override val variance: Variance
get() = Variance.INVARIANT
abstract override val classifier: IrClassifierSymbol abstract override val classifier: IrClassifierSymbol
abstract override val nullability: SimpleTypeNullability abstract override val nullability: SimpleTypeNullability
abstract override val arguments: List<IrTypeArgument> abstract override val arguments: List<IrTypeArgument>
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.model.CaptureStatus import org.jetbrains.kotlin.types.model.CaptureStatus
@@ -44,11 +45,7 @@ class IrDynamicTypeImpl(
val IrType.originalKotlinType: KotlinType? val IrType.originalKotlinType: KotlinType?
get() = (this as? IrTypeBase)?.kotlinType get() = (this as? IrTypeBase)?.kotlinType
object IrStarProjectionImpl : IrStarProjection { data object IrStarProjectionImpl : IrStarProjection
override fun equals(other: Any?): Boolean = this === other
override fun hashCode(): Int = System.identityHashCode(this)
}
/** /**
* An instance which should be used when creating an IR element whose type cannot be determined at the moment of creation. * An instance which should be used when creating an IR element whose type cannot be determined at the moment of creation.
@@ -60,15 +57,11 @@ object IrStarProjectionImpl : IrStarProjection {
* however this could lead to a situation where we forget to set return type sometimes. This would result in crashes at unexpected moments, * however this could lead to a situation where we forget to set return type sometimes. This would result in crashes at unexpected moments,
* especially in Kotlin/JS where function return types are not present in the resulting binary files. * especially in Kotlin/JS where function return types are not present in the resulting binary files.
*/ */
object IrUninitializedType : IrType() { data object IrUninitializedType : IrType() {
override val annotations: List<IrConstructorCall> = emptyList() override val annotations: List<IrConstructorCall> = emptyList()
override fun equals(other: Any?): Boolean = this === other
override fun hashCode(): Int = System.identityHashCode(this)
} }
class ReturnTypeIsNotInitializedException(function: IrFunction) : IllegalStateException( internal class ReturnTypeIsNotInitializedException(function: IrFunction) : IllegalStateException(
"Return type is not initialized for function '${function.name}'" "Return type is not initialized for function '${function.name}'"
) )
@@ -80,19 +73,12 @@ class IrCapturedType(
projection: IrTypeArgument, projection: IrTypeArgument,
typeParameter: IrTypeParameter typeParameter: IrTypeParameter
) : IrSimpleType(null), CapturedTypeMarker { ) : IrSimpleType(null), CapturedTypeMarker {
class Constructor(val argument: IrTypeArgument, val typeParameter: IrTypeParameter) : CapturedTypeConstructorMarker {
override val variance: Variance var superTypes: List<IrType> = emptyList()
get() = TODO("Not yet implemented") private set
class Constructor(val argument: IrTypeArgument, val typeParameter: IrTypeParameter) :
CapturedTypeConstructorMarker {
private var _superTypes: List<IrType> = emptyList()
val superTypes: List<IrType> get() = _superTypes
fun initSuperTypes(superTypes: List<IrType>) { fun initSuperTypes(superTypes: List<IrType>) {
_superTypes = superTypes this.superTypes = superTypes
} }
} }
@@ -100,18 +86,13 @@ class IrCapturedType(
override val classifier: IrClassifierSymbol get() = error("Captured Type does not have a classifier") override val classifier: IrClassifierSymbol get() = error("Captured Type does not have a classifier")
override val arguments: List<IrTypeArgument> get() = emptyList() override val arguments: List<IrTypeArgument> get() = emptyList()
override val abbreviation: IrTypeAbbreviation? get () = null override val abbreviation: IrTypeAbbreviation? get() = null
override val nullability: SimpleTypeNullability get() = SimpleTypeNullability.DEFINITELY_NOT_NULL override val nullability: SimpleTypeNullability get() = SimpleTypeNullability.DEFINITELY_NOT_NULL
override val annotations: List<IrConstructorCall> get() = emptyList() override val annotations: List<IrConstructorCall> get() = emptyList()
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean = this === other
return other is IrCapturedType
&& captureStatus == other.captureStatus
&& lowerType == other.lowerType
&& constructor === other.constructor
}
override fun hashCode(): Int { override fun hashCode(): Int = System.identityHashCode(this)
return (captureStatus.hashCode() * 31 + (lowerType?.hashCode() ?: 0)) * 31 + constructor.hashCode()
} override fun toString(): String = "IrCapturedType(${constructor.argument.render()}"
} }
@@ -8,8 +8,11 @@ package org.jetbrains.kotlin.backend.common.linkage.partial
import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.linkage.partial.ExploredClassifier import org.jetbrains.kotlin.ir.linkage.partial.ExploredClassifier
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrTypeAbbreviation
import org.jetbrains.kotlin.ir.types.IrTypeArgument
import org.jetbrains.kotlin.ir.types.SimpleTypeNullability
/** /**
* Replacement for IR types that reference unusable classifier symbols. * Replacement for IR types that reference unusable classifier symbols.
@@ -17,15 +20,14 @@ import org.jetbrains.kotlin.types.Variance
*/ */
internal class PartiallyLinkedMarkerType( internal class PartiallyLinkedMarkerType(
builtIns: IrBuiltIns, builtIns: IrBuiltIns,
val unusableClassifier: ExploredClassifier.Unusable val unusableClassifier: ExploredClassifier.Unusable,
) : IrSimpleType(null) { ) : IrSimpleType(null) {
override val annotations get() = emptyList<IrConstructorCall>() override val annotations: List<IrConstructorCall> get() = emptyList()
override val classifier = builtIns.anyClass override val classifier: IrClassSymbol = builtIns.anyClass
override val nullability get() = SimpleTypeNullability.MARKED_NULLABLE override val nullability: SimpleTypeNullability get() = SimpleTypeNullability.MARKED_NULLABLE
override val arguments get() = emptyList<IrTypeArgument>() override val arguments: List<IrTypeArgument> get() = emptyList()
override val abbreviation: IrTypeAbbreviation? get() = null override val abbreviation: IrTypeAbbreviation? get() = null
override val variance get() = Variance.INVARIANT
override fun equals(other: Any?) = (other as? PartiallyLinkedMarkerType)?.unusableClassifier == unusableClassifier override fun equals(other: Any?): Boolean = (other as? PartiallyLinkedMarkerType)?.unusableClassifier == unusableClassifier
override fun hashCode() = unusableClassifier.hashCode() override fun hashCode(): Int = unusableClassifier.hashCode()
} }