diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/CompilerConeAttributes.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/CompilerConeAttributes.kt index d1ccee6dab7..51b77c8182b 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/CompilerConeAttributes.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/CompilerConeAttributes.kt @@ -17,6 +17,8 @@ object CompilerConeAttributes { override fun union(other: Exact?): Exact? = null override fun intersect(other: Exact?): Exact? = null + override fun add(other: Exact?): Exact = this + override fun isSubtypeOf(other: Exact?): Boolean = true override val key: KClass = Exact::class @@ -29,6 +31,7 @@ object CompilerConeAttributes { override fun union(other: NoInfer?): NoInfer? = null override fun intersect(other: NoInfer?): NoInfer? = null + override fun add(other: NoInfer?): NoInfer = this override fun isSubtypeOf(other: NoInfer?): Boolean = true override val key: KClass = NoInfer::class @@ -41,6 +44,8 @@ object CompilerConeAttributes { override fun union(other: EnhancedNullability?): EnhancedNullability? = other override fun intersect(other: EnhancedNullability?): EnhancedNullability = this + override fun add(other: EnhancedNullability?): EnhancedNullability = this + override fun isSubtypeOf(other: EnhancedNullability?): Boolean = true override val key: KClass = EnhancedNullability::class @@ -53,6 +58,8 @@ object CompilerConeAttributes { override fun union(other: ExtensionFunctionType?): ExtensionFunctionType? = other override fun intersect(other: ExtensionFunctionType?): ExtensionFunctionType = this + override fun add(other: ExtensionFunctionType?): ExtensionFunctionType = this + override fun isSubtypeOf(other: ExtensionFunctionType?): Boolean = true override val key: KClass = ExtensionFunctionType::class @@ -65,6 +72,8 @@ object CompilerConeAttributes { override fun union(other: UnsafeVariance?): UnsafeVariance? = null override fun intersect(other: UnsafeVariance?): UnsafeVariance? = null + override fun add(other: UnsafeVariance?): UnsafeVariance = this + override fun isSubtypeOf(other: UnsafeVariance?): Boolean = true override val key: KClass = UnsafeVariance::class diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeAttributes.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeAttributes.kt index 1e5698af96d..657eba11336 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeAttributes.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeAttributes.kt @@ -15,6 +15,17 @@ import kotlin.reflect.KClass abstract class ConeAttribute> : AnnotationMarker { abstract fun union(other: @UnsafeVariance T?): T? abstract fun intersect(other: @UnsafeVariance T?): T? + + /* + * This function is used to decide how multiple attributes should be united in presence of typealiases: + * typealias B = @SomeAttribute(1) A + * typealias C = @SomeAttribute(2) B + * + * For determining attribute value of expanded type of C we should add @SomeAttribute(2) to @SomeAttribute(1) + * + * This function must be symmetrical: a.add(b) == b.add(a) + */ + abstract fun add(other: @UnsafeVariance T?): T abstract fun isSubtypeOf(other: @UnsafeVariance T?): Boolean abstract override fun toString(): String @@ -65,6 +76,10 @@ class ConeAttributes private constructor(attributes: List>) : A return perform(other) { this.intersect(it) } } + fun add(other: ConeAttributes): ConeAttributes { + return perform(other) { this.add(it) } + } + operator fun contains(attribute: ConeAttribute<*>): Boolean { val index = getId(attribute.key) return arrayMap[index] != null diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/TypeExpansionUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/TypeExpansionUtils.kt index 5236a5928c2..5022526ca98 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/TypeExpansionUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/TypeExpansionUtils.kt @@ -68,7 +68,10 @@ fun ConeClassLikeType.directExpansionType( val typeAliasSymbol = lookupTag.toSymbol(useSiteSession) as? FirTypeAliasSymbol ?: return null val typeAlias = typeAliasSymbol.fir - val resultType = expandedConeType(typeAlias)?.applyNullabilityFrom(useSiteSession, this) ?: return null + val resultType = expandedConeType(typeAlias) + ?.applyNullabilityFrom(useSiteSession, this) + ?.applyAttributesFrom(useSiteSession, this) + ?: return null if (resultType.typeArguments.isEmpty()) return resultType return mapTypeAliasArguments(typeAlias, this, resultType, useSiteSession) as? ConeClassLikeType @@ -82,6 +85,14 @@ private fun ConeClassLikeType.applyNullabilityFrom( return this } +private fun ConeClassLikeType.applyAttributesFrom( + session: FirSession, + abbreviation: ConeClassLikeType +): ConeClassLikeType { + val combinedAttributes = attributes.add(abbreviation.attributes) + return withAttributes(combinedAttributes, session.typeContext) +} + private fun mapTypeAliasArguments( typeAlias: FirTypeAlias, abbreviatedType: ConeClassLikeType, diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/CustomAnnotationTypeAttribute.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/CustomAnnotationTypeAttribute.kt index 04fdd602a09..f7fd8b284aa 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/CustomAnnotationTypeAttribute.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/CustomAnnotationTypeAttribute.kt @@ -14,6 +14,11 @@ class CustomAnnotationTypeAttribute(val annotations: List) : Cone override fun intersect(other: CustomAnnotationTypeAttribute?): CustomAnnotationTypeAttribute? = null + override fun add(other: CustomAnnotationTypeAttribute?): CustomAnnotationTypeAttribute { + if (other == null) return this + return CustomAnnotationTypeAttribute(annotations + other.annotations) + } + override fun isSubtypeOf(other: CustomAnnotationTypeAttribute?): Boolean = true override fun toString(): String = annotations.joinToString(separator = " ") { it.render() }