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 d358fc9f423..51d259bbba4 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 @@ -63,7 +63,11 @@ inline fun > ConeAttributeWithConeType.trans ): ConeAttributeWithConeType? { val transformedType = transform(coneType) ?: return null if (transformedType == coneType) return this - return copyWith(transformedType) + + // If the type contains the attribute itself, use the nested type from the attribute to prevent exponential growth. + // As an example, consider a substitution {T -> Attr(Foo) Bar} applied to a type `Attr(T) T`. + // If we don't flatten the attribute chain, we would get `Attr(Attr(Foo) Bar) Bar`. + return copyWith(transformedType.attributes[key]?.coneType ?: transformedType) } typealias ConeAttributeKey = KClass> @@ -120,8 +124,13 @@ class ConeAttributes private constructor(attributes: List>) : A } operator fun contains(attributeKey: KClass>): Boolean { + return get(attributeKey) != null + } + + operator fun > get(attributeKey: KClass) : T? { val index = getId(attributeKey) - return arrayMap[index] != null + @Suppress("UNCHECKED_CAST") + return arrayMap[index] as T? } operator fun plus(attribute: ConeAttribute<*>): ConeAttributes {