[FIR] do not copy annotations during type propagation

We should share the original instance to be able to later resolve it in
the original context. This commit returns the KT-60387 problem, but the
root cause (concurrent modification) will be fixed in the context of
KT-63042

^KT-63042
This commit is contained in:
Dmitrii Gridin
2023-11-24 15:20:13 +01:00
committed by Space Team
parent 69559689fd
commit 264a151676
12 changed files with 36 additions and 142 deletions
@@ -32,7 +32,7 @@ FILE: [ResolvedTo(IMPORTS)] lambdaAsSAMInterfaceWithAnnotation.kt
public final const [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] val constant: R|kotlin/Int| = Int(0)
public [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] get(): R|kotlin/Int|
public abstract fun [ResolvedTo(STATUS)] interface Foo : R|kotlin/Any| {
public abstract [ResolvedTo(STATUS)] fun foo([ResolvedTo(STATUS)] a: R|@R|foo/Anno|(<strcat>(String(foo param type ), R|foo/constant|)) foo/Arg|): R|@R|foo/Anno|(<strcat>(String(foo return type ), R|foo/constant|)) foo/Arg|
public abstract [ResolvedTo(STATUS)] fun foo([ResolvedTo(STATUS)] a: R|@R|foo/Anno|(position = <strcat>(String(foo param type ), R|foo/constant|)) foo/Arg|): R|@R|foo/Anno|(position = <strcat>(String(foo return type ), R|foo/constant|)) foo/Arg|
}
public final [ResolvedTo(CONTRACTS)] fun testMe([ResolvedTo(CONTRACTS)] f: R|@R|foo/Anno|(<strcat>(String(testMe param type ), constant#)) foo/Foo|): R|kotlin/Unit| {
@@ -200,8 +200,8 @@ FILE: [ResolvedTo(IMPORTS)] anonymousFunctionWithAnnotatedParameter.kt
public [ResolvedTo(STATUS)] [ContainingClassKey=Anno] get(): R|kotlin/String|
}
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(String(outer)) kotlin/collections/List<@R|Anno|(String(middle)) kotlin/collections/List<@R|Anno|(String(inner)) kotlin/Int>>?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(String(outer)) kotlin/collections/List<@R|Anno|(String(middle)) kotlin/collections/List<@R|Anno|(String(inner)) kotlin/Int>>?| {
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(message = String(outer)) kotlin/collections/List<@R|Anno|(message = String(middle)) kotlin/collections/List<@R|Anno|(message = String(inner)) kotlin/Int>>?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(message = String(outer)) kotlin/collections/List<@R|Anno|(message = String(middle)) kotlin/collections/List<@R|Anno|(message = String(inner)) kotlin/Int>>?| {
^ Null(null)
}
public final [ResolvedTo(BODY_RESOLVE)] val propertyToResolve: R|kotlin/String|
@@ -200,13 +200,13 @@ FILE: [ResolvedTo(IMPORTS)] anonymousFunctionWithAnnotatedParameter2.kt
public [ResolvedTo(STATUS)] [ContainingClassKey=Anno] get(): R|kotlin/String|
}
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(String(outer)) kotlin/collections/List<@R|Anno|(String(middle)) kotlin/collections/List<@R|Anno|(String(inner)) kotlin/Int>>?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(String(outer)) kotlin/collections/List<@R|Anno|(String(middle)) kotlin/collections/List<@R|Anno|(String(inner)) kotlin/Int>>?| {
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(message = String(outer)) kotlin/collections/List<@R|Anno|(message = String(middle)) kotlin/collections/List<@R|Anno|(message = String(inner)) kotlin/Int>>?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(message = String(outer)) kotlin/collections/List<@R|Anno|(message = String(middle)) kotlin/collections/List<@R|Anno|(message = String(inner)) kotlin/Int>>?| {
^ Null(null)
}
public final [ResolvedTo(BODY_RESOLVE)] val propertyToResolve: R|kotlin/String|
public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/String| {
^ R|/nullablePropertyWithAnnotatedType|.R|kotlin/let|<R|@R|Anno|(String(outer)) kotlin/collections/List<@R|Anno|(String(middle)) kotlin/collections/List<@R|Anno|(String(inner)) kotlin/Int>>?|, R|kotlin/String|>(<L> = [ResolvedTo(BODY_RESOLVE)] [MatchingParameterFunctionTypeKey=kotlin/Function1<T, R>] let@fun <anonymous>([ResolvedTo(BODY_RESOLVE)] it: R|@R|Anno|(message = String(outer)) kotlin/collections/List<@R|Anno|(message = String(middle)) kotlin/collections/List<@R|Anno|(message = String(inner)) kotlin/Int>>?|): R|kotlin/String| <inline=Inline, kind=EXACTLY_ONCE> {
^ R|/nullablePropertyWithAnnotatedType|.R|kotlin/let|<R|@R|Anno|(message = String(outer)) kotlin/collections/List<@R|Anno|(message = String(middle)) kotlin/collections/List<@R|Anno|(message = String(inner)) kotlin/Int>>?|, R|kotlin/String|>(<L> = [ResolvedTo(BODY_RESOLVE)] [MatchingParameterFunctionTypeKey=kotlin/Function1<T, R>] let@fun <anonymous>([ResolvedTo(BODY_RESOLVE)] it: R|@R|Anno|(message = String(outer)) kotlin/collections/List<@R|Anno|(message = String(middle)) kotlin/collections/List<@R|Anno|(message = String(inner)) kotlin/Int>>?|): R|kotlin/String| <inline=Inline, kind=EXACTLY_ONCE> {
^ <strcat>(String( (), R|<local>/it|, String()))
}
)
@@ -282,14 +282,14 @@ FILE: [ResolvedTo(IMPORTS)] anonymousFunctionWithAnnotatedParameter2Script.kts
}
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(String(outer)) kotlin/collections/List<@R|Anno|(String(middle)) kotlin/collections/List<@R|Anno|(String(inner)) kotlin/Int>>?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(String(outer)) kotlin/collections/List<@R|Anno|(String(middle)) kotlin/collections/List<@R|Anno|(String(inner)) kotlin/Int>>?| {
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(message = String(outer)) kotlin/collections/List<@R|Anno|(message = String(middle)) kotlin/collections/List<@R|Anno|(message = String(inner)) kotlin/Int>>?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(message = String(outer)) kotlin/collections/List<@R|Anno|(message = String(middle)) kotlin/collections/List<@R|Anno|(message = String(inner)) kotlin/Int>>?| {
^ Null(null)
}
public final [ResolvedTo(BODY_RESOLVE)] val propertyToResolve: R|kotlin/String|
public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/String| {
^ R|/nullablePropertyWithAnnotatedType|.R|kotlin/let|<R|@R|Anno|(String(outer)) kotlin/collections/List<@R|Anno|(String(middle)) kotlin/collections/List<@R|Anno|(String(inner)) kotlin/Int>>?|, R|kotlin/String|>(<L> = [ResolvedTo(BODY_RESOLVE)] [MatchingParameterFunctionTypeKey=kotlin/Function1<T, R>] let@fun <anonymous>([ResolvedTo(BODY_RESOLVE)] it: R|@R|Anno|(message = String(outer)) kotlin/collections/List<@R|Anno|(message = String(middle)) kotlin/collections/List<@R|Anno|(message = String(inner)) kotlin/Int>>?|): R|kotlin/String| <inline=Inline, kind=EXACTLY_ONCE> {
^ R|/nullablePropertyWithAnnotatedType|.R|kotlin/let|<R|@R|Anno|(message = String(outer)) kotlin/collections/List<@R|Anno|(message = String(middle)) kotlin/collections/List<@R|Anno|(message = String(inner)) kotlin/Int>>?|, R|kotlin/String|>(<L> = [ResolvedTo(BODY_RESOLVE)] [MatchingParameterFunctionTypeKey=kotlin/Function1<T, R>] let@fun <anonymous>([ResolvedTo(BODY_RESOLVE)] it: R|@R|Anno|(message = String(outer)) kotlin/collections/List<@R|Anno|(message = String(middle)) kotlin/collections/List<@R|Anno|(message = String(inner)) kotlin/Int>>?|): R|kotlin/String| <inline=Inline, kind=EXACTLY_ONCE> {
^ <strcat>(String( (), R|<local>/it|, String()))
}
)
@@ -324,3 +324,4 @@ FILE: [ResolvedTo(BODY_RESOLVE)] anonymousFunctionWithAnnotatedParameter2Script.
}
)
}
@@ -158,8 +158,8 @@ FILE: [ResolvedTo(IMPORTS)] anonymousFunctionWithAnnotatedParameterOnImplicitTyp
public [ResolvedTo(STATUS)] [ContainingClassKey=Anno] get(): R|kotlin/String|
}
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(String(str)) kotlin/String?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(String(str)) kotlin/String?| {
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(message = String(str)) kotlin/String?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(message = String(str)) kotlin/String?| {
^ Null(null)
}
public final [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] val propertyToResolve: R|kotlin/String|
@@ -181,8 +181,8 @@ FILE: [ResolvedTo(IMPORTS)] anonymousFunctionWithAnnotatedParameterOnImplicitTyp
public [ResolvedTo(STATUS)] [ContainingClassKey=Anno] get(): R|kotlin/String|
}
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(String(str)) kotlin/String?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(String(str)) kotlin/String?| {
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(message = String(str)) kotlin/String?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(message = String(str)) kotlin/String?| {
^ Null(null)
}
public final [ResolvedTo(ANNOTATION_ARGUMENTS)] val propertyToResolve: R|kotlin/String|
@@ -204,8 +204,8 @@ FILE: [ResolvedTo(IMPORTS)] anonymousFunctionWithAnnotatedParameterOnImplicitTyp
public [ResolvedTo(STATUS)] [ContainingClassKey=Anno] get(): R|kotlin/String|
}
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(String(str)) kotlin/String?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(String(str)) kotlin/String?| {
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(message = String(str)) kotlin/String?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(message = String(str)) kotlin/String?| {
^ Null(null)
}
public final [ResolvedTo(BODY_RESOLVE)] val propertyToResolve: R|kotlin/String|
@@ -226,8 +226,8 @@ FILE: [ResolvedTo(IMPORTS)] anonymousFunctionWithAnnotatedParameterOnImplicitTyp
}
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(String(str)) kotlin/String?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(String(str)) kotlin/String?| {
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(message = String(str)) kotlin/String?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(message = String(str)) kotlin/String?| {
^ Null(null)
}
@@ -256,8 +256,8 @@ FILE: [ResolvedTo(IMPORTS)] anonymousFunctionWithAnnotatedParameterOnImplicitTyp
}
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(String(str)) kotlin/String?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(String(str)) kotlin/String?| {
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(message = String(str)) kotlin/String?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(message = String(str)) kotlin/String?| {
^ Null(null)
}
@@ -286,8 +286,8 @@ FILE: [ResolvedTo(IMPORTS)] anonymousFunctionWithAnnotatedParameterOnImplicitTyp
}
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(String(str)) kotlin/String?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(String(str)) kotlin/String?| {
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(message = String(str)) kotlin/String?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(message = String(str)) kotlin/String?| {
^ Null(null)
}
@@ -328,3 +328,4 @@ FILE: [ResolvedTo(BODY_RESOLVE)] anonymousFunctionWithAnnotatedParameterOnImplic
}
) } ?: String()
}
@@ -282,8 +282,8 @@ FILE: [ResolvedTo(IMPORTS)] anonymousFunctionWithAnnotatedParameterScript.kts
}
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(String(outer)) kotlin/collections/List<@R|Anno|(String(middle)) kotlin/collections/List<@R|Anno|(String(inner)) kotlin/Int>>?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(String(outer)) kotlin/collections/List<@R|Anno|(String(middle)) kotlin/collections/List<@R|Anno|(String(inner)) kotlin/Int>>?| {
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(message = String(outer)) kotlin/collections/List<@R|Anno|(message = String(middle)) kotlin/collections/List<@R|Anno|(message = String(inner)) kotlin/Int>>?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(message = String(outer)) kotlin/collections/List<@R|Anno|(message = String(middle)) kotlin/collections/List<@R|Anno|(message = String(inner)) kotlin/Int>>?| {
^ Null(null)
}
@@ -324,3 +324,4 @@ FILE: [ResolvedTo(BODY_RESOLVE)] anonymousFunctionWithAnnotatedParameterScript.k
}
) } ?: String()
}
@@ -294,8 +294,8 @@ FILE: [ResolvedTo(IMPORTS)] declaration.kt
public [ResolvedTo(STATUS)] [ContainingClassKey=Anno] get(): R|kotlin/String|
}
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(R|/privateConstant<HIDDEN: /privateConstant is invisible>#|) kotlin/collections/List<@R|Anno|(R|/internalConstant<HIDDEN: /internalConstant is invisible>#|) kotlin/collections/List<@R|Anno|(R|/regularConstant|) kotlin/Int>>?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(R|/privateConstant<HIDDEN: /privateConstant is invisible>#|) kotlin/collections/List<@R|Anno|(R|/internalConstant<HIDDEN: /internalConstant is invisible>#|) kotlin/collections/List<@R|Anno|(R|/regularConstant|) kotlin/Int>>?| {
public final [ResolvedTo(CONTRACTS)] val nullablePropertyWithAnnotatedType: R|@R|Anno|(message = R|/privateConstant<HIDDEN: /privateConstant is invisible>#|) kotlin/collections/List<@R|Anno|(message = R|/internalConstant<HIDDEN: /internalConstant is invisible>#|) kotlin/collections/List<@R|Anno|(message = R|/regularConstant|) kotlin/Int>>?|
public [ResolvedTo(CONTRACTS)] get(): R|@R|Anno|(message = R|/privateConstant<HIDDEN: /privateConstant is invisible>#|) kotlin/collections/List<@R|Anno|(message = R|/internalConstant<HIDDEN: /internalConstant is invisible>#|) kotlin/collections/List<@R|Anno|(message = R|/regularConstant|) kotlin/Int>>?| {
^ Null(null)
}
@@ -106,89 +106,6 @@ fun ConeDynamicType.Companion.create(
session.builtinTypes.nullableAnyType.type.withAttributes(attributes),
)
/**
* This call is required if you want to use a type with annotations that are linked to a declaration from this declaration inside another
* to avoid concurrent modification problems (see KT-60387).
*
* Otherwise, those annotations can be transformed from different threads simultaneously that is error-prone.
* Example:
* ```kotlin
* val declaration: @Anno("outer") Int? get() = null
* val anotherDeclaration: String get() = declaration?.let { "$it" }.toString()
* ```
* here for `declaration?.let { "$it" }` will be created an anonymous function with argument that
* will have the same type as the return type of `declaration`.
* So, now we have 2 possible scenarios:
*
* Wrong case 1 The type was inserted to a new type ref as it is.
* This means that a type reference from `declaration` and from the anonymous lambda will have the same instance of `Anno`.
* Now we resole `anotherDeclaration` to [FirResolvePhase.BODY_RESOLVE] phase
* and as a result we will have resolved annotation arguments in the type.
* At the same time, `declaration` can be still in [FirResolvePhase.CONTRACTS] phase, because no one called a resolution yet.
* So now imagine a situation when one thread (1) wants to read annotation arguments from the fully resolved anonymous function,
* and another thread (2) wants to resolve `declaration` to [FirResolvePhase.ANNOTATION_ARGUMENTS] phase.
* As a result, we will have a moment there thread 2 will replace arguments with a lazy expression
* to be sure that we will have a safe basis for resolution (see StateKeeper concept in LL FIR).
* And thread 1 will see unexpected unresolved annotation arguments in fully resolved function, because those type references
* use the same instance of the type (`FirArgumentListImpl` cannot be cast to `FirResolvedArgumentList`).
* So we lost here.
*
* Right case 2 The type was "copied" by [independentInstance].
* In this case, `declaration` and `anotherDeclaration` will have different instances of one `@Anno("outer") Int?` type.
* This means that we can't come to a situation where we can modify a fully resolved annotation from another thread.
*
* @return an instance of a type that has no annotations associated with any declaration,
* so it won't be changed from LL FIR lazy transformers concurrently
*
* @see CustomAnnotationTypeAttribute.independentInstance
*/
@OptIn(DynamicTypeConstructor::class)
fun ConeKotlinType.independentInstance(): ConeKotlinType = if (this is ConeFlexibleType) {
val newLowerBound = lowerBound.independentInstance() as ConeSimpleKotlinType
val newUpperBound = upperBound.independentInstance() as ConeSimpleKotlinType
if (newLowerBound !== lowerBound || newUpperBound !== upperBound) {
when (this) {
is ConeRawType -> ConeRawType.create(newLowerBound, newUpperBound)
is ConeDynamicType -> ConeDynamicType(newLowerBound, newUpperBound)
else -> ConeFlexibleType(newLowerBound, newUpperBound)
}
} else {
this
}
} else {
instanceWithIndependentArguments().instanceWithIndependentAnnotations()
}
private fun ConeKotlinType.instanceWithIndependentArguments(): ConeKotlinType {
val typeProjections = typeArguments
if (typeProjections.isEmpty()) return this
var argumentsChanged = false
val newArguments = type.typeArguments.map { originalArgument ->
if (originalArgument !is ConeKotlinType)
originalArgument
else
originalArgument.independentInstance().also {
if (it !== originalArgument) {
argumentsChanged = true
}
}
}
return if (argumentsChanged) withArguments(newArguments.toTypedArray()) else this
}
private fun ConeKotlinType.instanceWithIndependentAnnotations(): ConeKotlinType {
val custom = attributes.custom ?: return this
val newAnnotations = custom.independentInstance()
if (newAnnotations === custom) {
return this
}
val newAttributes = attributes.remove(custom).plus(newAnnotations)
return withAttributes(newAttributes)
}
fun ConeKotlinType.makeConeTypeDefinitelyNotNullOrNotNull(
typeContext: ConeTypeContext,
avoidComprehensiveCheck: Boolean = false,
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -476,10 +476,9 @@ fun FirCheckedSafeCallSubject.propagateTypeFromOriginalReceiver(
?.coneTypeSafe<ConeKotlinType>()
?: nullableReceiverExpression.resolvedType
val expandedReceiverType = receiverType.fullyExpandedType(session)
val updatedReceiverType = expandedReceiverType.makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext).independentInstance()
replaceConeTypeOrNull(updatedReceiverType)
session.lookupTracker?.recordTypeResolveAsLookup(updatedReceiverType, source, file.source)
val expandedReceiverType = receiverType.fullyExpandedType(session).makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext)
replaceConeTypeOrNull(expandedReceiverType)
session.lookupTracker?.recordTypeResolveAsLookup(expandedReceiverType, source, file.source)
}
fun FirSafeCallExpression.propagateTypeFromQualifiedAccessAfterNullCheck(
@@ -500,9 +499,8 @@ fun FirSafeCallExpression.propagateTypeFromQualifiedAccessAfterNullCheck(
}
}
val independentInstance = resultingType.independentInstance()
replaceConeTypeOrNull(independentInstance)
session.lookupTracker?.recordTypeResolveAsLookup(independentInstance, source, file.source)
replaceConeTypeOrNull(resultingType)
session.lookupTracker?.recordTypeResolveAsLookup(resultingType, source, file.source)
}
fun FirAnnotation.getCorrespondingClassSymbolOrNull(session: FirSession): FirRegularClassSymbol? {
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -110,7 +110,7 @@ class PostponedArgumentsAnalyzer(
val stubsForPostponedVariables = c.bindingStubsForPostponedVariables()
val currentSubstitutor = c.buildCurrentSubstitutor(stubsForPostponedVariables.mapKeys { it.key.freshTypeConstructor(c) })
fun substitute(type: ConeKotlinType) = (currentSubstitutor.safeSubstitute(c, type) as ConeKotlinType).independentInstance()
fun substitute(type: ConeKotlinType) = currentSubstitutor.safeSubstitute(c, type) as ConeKotlinType
val receiver = lambda.receiver?.let(::substitute)
val contextReceivers = lambda.contextReceivers.map(::substitute)
@@ -6,9 +6,6 @@
package org.jetbrains.kotlin.fir.types
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCallCopy
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCopy
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.renderer.FirRenderer
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
@@ -63,27 +60,6 @@ class CustomAnnotationTypeAttribute(
get() = CustomAnnotationTypeAttribute::class
override val keepInInferredDeclarationType: Boolean
get() = true
/**
* Return an instance of the attribute that is not linked to any [containerSymbols].
* It is required to avoid concurrent modification of those annotations from the linked
* declaration and another call site (e.g., if a type was propagated to an anonymous function).
*
* See KT-60387 as an example of a possible concurrent problem.
*/
fun independentInstance(): CustomAnnotationTypeAttribute = if (containerSymbols.isEmpty()) {
this
} else {
CustomAnnotationTypeAttribute(
annotations = annotations.map {
if (it is FirAnnotationCall) {
buildAnnotationCallCopy(it) {}
} else {
buildAnnotationCopy(it) {}
}
}
)
}
}
val ConeAttributes.custom: CustomAnnotationTypeAttribute? by ConeAttributes.attributeAccessor<CustomAnnotationTypeAttribute>()