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
get() = nullability == SimpleTypeNullability.MARKED_NULLABLE
override val variance: Variance
get() = Variance.INVARIANT
}
/**
@@ -90,7 +90,7 @@ class IrTypeSubstitutor(
override fun isEmptySubstitution(): Boolean = substitution.isEmpty()
}
class IrCapturedTypeSubstitutor(
internal class IrCapturedTypeSubstitutor(
typeParameters: List<IrTypeParameterSymbol>,
typeArguments: List<IrTypeArgument>,
capturedTypes: List<IrCapturedType?>,
@@ -239,9 +239,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
*
* See https://kotlinlang.org/spec/type-system.html#type-capturing
*/
override fun captureFromArguments(type: SimpleTypeMarker, status: CaptureStatus): SimpleTypeMarker? {
// TODO: is that correct?
require(type is IrSimpleType)
if (type is IrCapturedType) return null
@@ -252,43 +250,33 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
if (!classifier.isBound) return null
val typeParameters = extractTypeParameters(classifier.owner)
require(typeArguments.size == typeParameters.size)
if (typeArguments.all { it is IrTypeProjection && it.variance == Variance.INVARIANT }) return type
val capturedTypes = ArrayList<IrCapturedType?>(typeArguments.size)
for (index in typeArguments.indices) {
val parameter = typeParameters[index]
val argument = typeArguments[index]
val capturedTypes = typeArguments.mapIndexed { index, argument ->
if (argument is IrTypeProjection && argument.variance == Variance.INVARIANT) {
capturedTypes.add(null)
null
} else {
val lowerType = if (argument is IrTypeProjection && argument.variance == Variance.IN_VARIANCE) {
argument.type
} 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)
for (index in typeArguments.indices) {
val oldArgument = typeArguments[index]
val parameter = typeParameters[index]
val newArguments = typeArguments.mapIndexed { index, oldArgument ->
val capturedType = capturedTypes[index]
if (capturedType == null) {
assert(oldArgument is IrTypeProjection && oldArgument.variance == Variance.INVARIANT)
newArguments.add(oldArgument)
oldArgument
} else {
val capturedSuperTypes = mutableListOf<IrType>()
parameter.superTypes.mapTo(capturedSuperTypes) {
typeParameters[index].superTypes.mapTo(capturedSuperTypes) {
typeSubstitutor.substitute(it)
}
@@ -298,7 +286,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
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.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.utils.compactIfPossible
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.compactIfPossible
abstract class IrAbstractSimpleType(kotlinType: KotlinType?) : IrSimpleType(kotlinType) {
override val variance: Variance
get() = Variance.INVARIANT
abstract override val classifier: IrClassifierSymbol
abstract override val nullability: SimpleTypeNullability
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.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.model.CaptureStatus
@@ -44,11 +45,7 @@ class IrDynamicTypeImpl(
val IrType.originalKotlinType: KotlinType?
get() = (this as? IrTypeBase)?.kotlinType
object IrStarProjectionImpl : IrStarProjection {
override fun equals(other: Any?): Boolean = this === other
override fun hashCode(): Int = System.identityHashCode(this)
}
data object IrStarProjectionImpl : IrStarProjection
/**
* 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,
* 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 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}'"
)
@@ -80,19 +73,12 @@ class IrCapturedType(
projection: IrTypeArgument,
typeParameter: IrTypeParameter
) : IrSimpleType(null), CapturedTypeMarker {
override val variance: Variance
get() = TODO("Not yet implemented")
class Constructor(val argument: IrTypeArgument, val typeParameter: IrTypeParameter) :
CapturedTypeConstructorMarker {
private var _superTypes: List<IrType> = emptyList()
val superTypes: List<IrType> get() = _superTypes
class Constructor(val argument: IrTypeArgument, val typeParameter: IrTypeParameter) : CapturedTypeConstructorMarker {
var superTypes: List<IrType> = emptyList()
private set
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 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 annotations: List<IrConstructorCall> get() = emptyList()
override fun equals(other: Any?): Boolean {
return other is IrCapturedType
&& captureStatus == other.captureStatus
&& lowerType == other.lowerType
&& constructor === other.constructor
}
override fun equals(other: Any?): Boolean = this === other
override fun hashCode(): Int {
return (captureStatus.hashCode() * 31 + (lowerType?.hashCode() ?: 0)) * 31 + constructor.hashCode()
}
override fun hashCode(): Int = System.identityHashCode(this)
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.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.linkage.partial.ExploredClassifier
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
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.
@@ -17,15 +20,14 @@ import org.jetbrains.kotlin.types.Variance
*/
internal class PartiallyLinkedMarkerType(
builtIns: IrBuiltIns,
val unusableClassifier: ExploredClassifier.Unusable
val unusableClassifier: ExploredClassifier.Unusable,
) : IrSimpleType(null) {
override val annotations get() = emptyList<IrConstructorCall>()
override val classifier = builtIns.anyClass
override val nullability get() = SimpleTypeNullability.MARKED_NULLABLE
override val arguments get() = emptyList<IrTypeArgument>()
override val annotations: List<IrConstructorCall> get() = emptyList()
override val classifier: IrClassSymbol = builtIns.anyClass
override val nullability: SimpleTypeNullability get() = SimpleTypeNullability.MARKED_NULLABLE
override val arguments: List<IrTypeArgument> get() = emptyList()
override val abbreviation: IrTypeAbbreviation? get() = null
override val variance get() = Variance.INVARIANT
override fun equals(other: Any?) = (other as? PartiallyLinkedMarkerType)?.unusableClassifier == unusableClassifier
override fun hashCode() = unusableClassifier.hashCode()
override fun equals(other: Any?): Boolean = (other as? PartiallyLinkedMarkerType)?.unusableClassifier == unusableClassifier
override fun hashCode(): Int = unusableClassifier.hashCode()
}