[FIR] Implement a special type of attribute that contains a cone type that can be transformed
This commit is contained in:
committed by
Space Team
parent
8ebd2fd1b7
commit
7910e8ad24
@@ -8,13 +8,14 @@ package org.jetbrains.kotlin.fir.types
|
|||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
class AbbreviatedTypeAttribute(
|
class AbbreviatedTypeAttribute(
|
||||||
val coneType: ConeKotlinType,
|
override val coneType: ConeKotlinType,
|
||||||
) : ConeAttribute<AbbreviatedTypeAttribute>() {
|
) : ConeAttributeWithConeType<AbbreviatedTypeAttribute>() {
|
||||||
override fun union(other: AbbreviatedTypeAttribute?): AbbreviatedTypeAttribute? = null
|
override fun union(other: AbbreviatedTypeAttribute?): AbbreviatedTypeAttribute? = null
|
||||||
override fun intersect(other: AbbreviatedTypeAttribute?): AbbreviatedTypeAttribute? = null
|
override fun intersect(other: AbbreviatedTypeAttribute?): AbbreviatedTypeAttribute? = null
|
||||||
override fun add(other: AbbreviatedTypeAttribute?): AbbreviatedTypeAttribute = other ?: this
|
override fun add(other: AbbreviatedTypeAttribute?): AbbreviatedTypeAttribute = other ?: this
|
||||||
override fun isSubtypeOf(other: AbbreviatedTypeAttribute?): Boolean = true
|
override fun isSubtypeOf(other: AbbreviatedTypeAttribute?): Boolean = true
|
||||||
override fun toString(): String = "{${coneType.renderForDebugging()}=}"
|
override fun toString(): String = "{${coneType.renderForDebugging()}=}"
|
||||||
|
override fun copyWith(newType: ConeKotlinType): AbbreviatedTypeAttribute = AbbreviatedTypeAttribute(newType)
|
||||||
|
|
||||||
override val key: KClass<out AbbreviatedTypeAttribute>
|
override val key: KClass<out AbbreviatedTypeAttribute>
|
||||||
get() = AbbreviatedTypeAttribute::class
|
get() = AbbreviatedTypeAttribute::class
|
||||||
|
|||||||
@@ -40,6 +40,25 @@ abstract class ConeAttribute<out T : ConeAttribute<T>> : AnnotationMarker {
|
|||||||
abstract val keepInInferredDeclarationType: Boolean
|
abstract val keepInInferredDeclarationType: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An attribute that contains a [ConeKotlinType].
|
||||||
|
* It is assumed that the [coneType] in this attribute is somehow related to the type it is attached to.
|
||||||
|
* Therefore, when the type is transformed (e.g., substitution, making not-null), the same transformation is applied to the attribute.
|
||||||
|
*/
|
||||||
|
abstract class ConeAttributeWithConeType<out T : ConeAttributeWithConeType<T>> : ConeAttribute<T>() {
|
||||||
|
abstract val coneType: ConeKotlinType
|
||||||
|
|
||||||
|
abstract fun copyWith(newType: ConeKotlinType): T
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <T : ConeAttributeWithConeType<T>> ConeAttributeWithConeType<T>.transformOrNull(
|
||||||
|
transform: (ConeKotlinType) -> ConeKotlinType?,
|
||||||
|
): ConeAttributeWithConeType<T>? {
|
||||||
|
val transformedType = transform(coneType) ?: return null
|
||||||
|
if (transformedType == coneType) return this
|
||||||
|
return copyWith(transformedType)
|
||||||
|
}
|
||||||
|
|
||||||
typealias ConeAttributeKey = KClass<out ConeAttribute<*>>
|
typealias ConeAttributeKey = KClass<out ConeAttribute<*>>
|
||||||
|
|
||||||
class ConeAttributes private constructor(attributes: List<ConeAttribute<*>>) : AttributeArrayOwner<ConeAttribute<*>, ConeAttribute<*>>(),
|
class ConeAttributes private constructor(attributes: List<ConeAttribute<*>>) : AttributeArrayOwner<ConeAttribute<*>, ConeAttribute<*>>(),
|
||||||
@@ -116,15 +135,6 @@ class ConeAttributes private constructor(attributes: List<ConeAttribute<*>>) : A
|
|||||||
return create(attributes)
|
return create(attributes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun replace(oldAttribute: ConeAttribute<*>, newAttribute: ConeAttribute<*>): ConeAttributes {
|
|
||||||
return create(buildList {
|
|
||||||
arrayMap.mapNotNullTo(this) { attr ->
|
|
||||||
attr.takeUnless { it == oldAttribute }
|
|
||||||
}
|
|
||||||
add(newAttribute)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun filterNecessaryToKeep(): ConeAttributes {
|
fun filterNecessaryToKeep(): ConeAttributes {
|
||||||
return if (all { it.keepInInferredDeclarationType }) this
|
return if (all { it.keepInInferredDeclarationType }) this
|
||||||
else create(filter { it.keepInInferredDeclarationType })
|
else create(filter { it.keepInInferredDeclarationType })
|
||||||
@@ -142,6 +152,34 @@ class ConeAttributes private constructor(attributes: List<ConeAttribute<*>>) : A
|
|||||||
return create(attributes)
|
return create(attributes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the [transform] to all attributes that are subtypes of [ConeAttributeWithConeType] and returns a [ConeAttributes]
|
||||||
|
* with the results of transforms that were not-`null` or `null` if no attributes were transformed.
|
||||||
|
*/
|
||||||
|
inline fun transformTypesWith(transform: (ConeKotlinType) -> ConeKotlinType?): ConeAttributes? {
|
||||||
|
if (isEmpty()) return null
|
||||||
|
|
||||||
|
// List will be allocated on demand
|
||||||
|
var newList: MutableList<ConeAttribute<*>>? = null
|
||||||
|
var hasDifference = false
|
||||||
|
|
||||||
|
for ((i, attr) in this.withIndex()) {
|
||||||
|
if (attr !is ConeAttributeWithConeType) continue
|
||||||
|
val substitutedAttribute = attr.transformOrNull(transform) ?: continue
|
||||||
|
if (newList == null) {
|
||||||
|
newList = this.toMutableList()
|
||||||
|
}
|
||||||
|
newList[i] = substitutedAttribute
|
||||||
|
hasDifference = hasDifference || substitutedAttribute != attr
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newList != null && !hasDifference) {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
return newList?.let(Companion::create)
|
||||||
|
}
|
||||||
|
|
||||||
override val typeRegistry: TypeRegistry<ConeAttribute<*>, ConeAttribute<*>>
|
override val typeRegistry: TypeRegistry<ConeAttribute<*>, ConeAttribute<*>>
|
||||||
get() = Companion
|
get() = Companion
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-9
@@ -59,7 +59,7 @@ abstract class AbstractConeSubstitutor(protected val typeContext: ConeTypeContex
|
|||||||
}
|
}
|
||||||
|
|
||||||
val substitutedType = newType ?: type.substituteRecursive()
|
val substitutedType = newType ?: type.substituteRecursive()
|
||||||
val substitutedAttributes = (substitutedType ?: type).attributes.substituteAbbreviationOrNull()
|
val substitutedAttributes = (substitutedType ?: type).attributes.transformTypesWith(this::substituteOrNull)
|
||||||
|
|
||||||
return if (substitutedType != null || substitutedAttributes != null) {
|
return if (substitutedType != null || substitutedAttributes != null) {
|
||||||
var result = substitutedType ?: type
|
var result = substitutedType ?: type
|
||||||
@@ -74,14 +74,6 @@ abstract class AbstractConeSubstitutor(protected val typeContext: ConeTypeContex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ConeAttributes.substituteAbbreviationOrNull(): ConeAttributes? {
|
|
||||||
val abbreviatedTypeAttribute = abbreviatedType ?: return null
|
|
||||||
substituteOrNull(abbreviatedTypeAttribute.coneType)?.let {
|
|
||||||
return replace(abbreviatedTypeAttribute, AbbreviatedTypeAttribute(it))
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ConeKotlinType.substituteRecursive(): ConeKotlinType? {
|
private fun ConeKotlinType.substituteRecursive(): ConeKotlinType? {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is ConeClassLikeType -> this.substituteArguments()
|
is ConeClassLikeType -> this.substituteArguments()
|
||||||
|
|||||||
Reference in New Issue
Block a user