From b03e3f0b0d49ea4fb6b5f1898995fd1ab4ee29f0 Mon Sep 17 00:00:00 2001 From: Dmitrii Gridin Date: Mon, 16 Oct 2023 19:46:20 +0200 Subject: [PATCH] [LL FIR] pass correct context during class annotation arguments mapping The root cause of the problem is that we visit class annotations more accurately than in the regular compiler transformer, so we have a difference: the compiler assumes that annotation processing of the class is called already inside this class, so it should enable CLASS_HEADER_ANNOTATIONS mode to not capture extra context. But we in LL FIR do this out of the class, so such context switching is redundant and results in cutting out the outer class context ^KT-62587 Fixed --- .../LLFirAnnotationArgumentsLazyResolver.kt | 16 ++++++++++---- .../annotationWithConstantFromNestedClass.txt | 14 ++++++------ .../nestedClassAsAnnotationArgument.txt | 6 ++--- .../nestedClassAsAnnotationArgument2.txt | 6 ++--- .../body/resolve/BodyResolveContext.kt | 22 +++++++++++++++++-- ...ntFromOuterScopeAsAnnotaionParameter.ll.kt | 14 ------------ .../nestedClassAsAnnotationParameter.ll.kt | 15 ------------- ...nestedClassAsIsAsAnnotationParameter.ll.kt | 14 ------------ .../nestedObjectAsAnnotationParameter.ll.kt | 15 ------------- 9 files changed, 45 insertions(+), 77 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/annotations/constantFromOuterScopeAsAnnotaionParameter.ll.kt delete mode 100644 compiler/testData/diagnostics/tests/annotations/nestedClassAsAnnotationParameter.ll.kt delete mode 100644 compiler/testData/diagnostics/tests/annotations/nestedClassAsIsAsAnnotationParameter.ll.kt delete mode 100644 compiler/testData/diagnostics/tests/annotations/nestedObjectAsAnnotationParameter.ll.kt diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentsLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentsLazyResolver.kt index fa323eccc1a..1eb91390ab7 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentsLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentsLazyResolver.kt @@ -12,7 +12,6 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodie import org.jetbrains.kotlin.fir.FirElementWithResolveState import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.util.PrivateForInline import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ScopeSession @@ -20,6 +19,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveCon import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirAnnotationArgumentsResolveTransformer import org.jetbrains.kotlin.fir.visitors.transformSingle +import org.jetbrains.kotlin.util.PrivateForInline internal object LLFirAnnotationArgumentsLazyResolver : LLFirLazyResolver(FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS) { override fun resolve( @@ -154,9 +154,17 @@ private class LLFirAnnotationArgumentsTargetResolver( internal fun LLFirAbstractBodyTargetResolver.transformAnnotations(target: FirElementWithResolveState) { when { target is FirRegularClass -> transformer.declarationsTransformer?.let { declarationsTransformer -> - target.transformAnnotations(declarationsTransformer, ResolutionMode.ContextIndependent) - target.transformTypeParameters(declarationsTransformer, ResolutionMode.ContextIndependent) - target.transformSuperTypeRefs(declarationsTransformer, ResolutionMode.ContextIndependent) + if (this is LLFirAnnotationArgumentsTargetResolver) { + target.transformAnnotations(declarationsTransformer, ResolutionMode.ContextIndependent) + target.transformTypeParameters(declarationsTransformer, ResolutionMode.ContextIndependent) + target.transformSuperTypeRefs(declarationsTransformer, ResolutionMode.ContextIndependent) + } else { + declarationsTransformer.context.insideClassHeader { + target.transformAnnotations(declarationsTransformer, ResolutionMode.ContextIndependent) + target.transformTypeParameters(declarationsTransformer, ResolutionMode.ContextIndependent) + target.transformSuperTypeRefs(declarationsTransformer, ResolutionMode.ContextIndependent) + } + } } target is FirScript -> { diff --git a/analysis/low-level-api-fir/testData/lazyResolve/classes/annotationWithConstantFromNestedClass.txt b/analysis/low-level-api-fir/testData/lazyResolve/classes/annotationWithConstantFromNestedClass.txt index 0849622d989..0586a32df0d 100644 --- a/analysis/low-level-api-fir/testData/lazyResolve/classes/annotationWithConstantFromNestedClass.txt +++ b/analysis/low-level-api-fir/testData/lazyResolve/classes/annotationWithConstantFromNestedClass.txt @@ -404,10 +404,10 @@ FILE: [ResolvedTo(IMPORTS)] annotationWithConstantFromNestedClass.kt LAZY_super } - public final const [ResolvedTo(STATUS)] val CONSTANT_FROM_COMPANION: = LAZY_EXPRESSION - public [ResolvedTo(STATUS)] [ContainingClassKey=Companion] get(): + public final const [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] val CONSTANT_FROM_COMPANION: R|kotlin/Int| = Int(42) + public [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] [ContainingClassKey=Companion] get(): R|kotlin/Int| - @R|Anno|[Types](number = #) public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] class Nested : R|kotlin/Any| { + @R|Anno|[Types](number = this@R|/Outer.Companion|.R|/Outer.Companion.CONSTANT_FROM_COMPANION|) public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] class Nested : R|kotlin/Any| { public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Nested] constructor(): R|Outer.Companion.Nested| { LAZY_super } @@ -439,10 +439,10 @@ FILE: [ResolvedTo(IMPORTS)] annotationWithConstantFromNestedClass.kt LAZY_super } - public final const [ResolvedTo(STATUS)] val CONSTANT_FROM_COMPANION: = LAZY_EXPRESSION - public [ResolvedTo(STATUS)] [ContainingClassKey=Companion] get(): + public final const [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] val CONSTANT_FROM_COMPANION: R|kotlin/Int| = Int(42) + public [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] [ContainingClassKey=Companion] get(): R|kotlin/Int| - @R|Anno|[Types](number = #) public final [ResolvedTo(BODY_RESOLVE)] class Nested : R|kotlin/Any| { + @R|Anno|[Types](number = this@R|/Outer.Companion|.R|/Outer.Companion.CONSTANT_FROM_COMPANION|) public final [ResolvedTo(BODY_RESOLVE)] class Nested : R|kotlin/Any| { public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=Nested] constructor(): R|Outer.Companion.Nested| { super() } @@ -477,7 +477,7 @@ FILE: [ResolvedTo(BODY_RESOLVE)] annotationWithConstantFromNestedClass.kt public final const [ResolvedTo(BODY_RESOLVE)] val CONSTANT_FROM_COMPANION: R|kotlin/Int| = Int(42) public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=Companion] get(): R|kotlin/Int| - @R|Anno|[Types](number = #) public final [ResolvedTo(BODY_RESOLVE)] class Nested : R|kotlin/Any| { + @R|Anno|[Types](number = this@R|/Outer.Companion|.R|/Outer.Companion.CONSTANT_FROM_COMPANION|) public final [ResolvedTo(BODY_RESOLVE)] class Nested : R|kotlin/Any| { public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=Nested] constructor(): R|Outer.Companion.Nested| { super() } diff --git a/analysis/low-level-api-fir/testData/lazyResolve/classes/nestedClassAsAnnotationArgument.txt b/analysis/low-level-api-fir/testData/lazyResolve/classes/nestedClassAsAnnotationArgument.txt index ccbc7a6d2e8..f9c04179189 100644 --- a/analysis/low-level-api-fir/testData/lazyResolve/classes/nestedClassAsAnnotationArgument.txt +++ b/analysis/low-level-api-fir/testData/lazyResolve/classes/nestedClassAsAnnotationArgument.txt @@ -313,7 +313,7 @@ FILE: [ResolvedTo(IMPORTS)] nestedClassAsAnnotationArgument.kt LAZY_super } - @R|Special|[Types](why = (#)) public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] class Nested<@R|Special|[Types](why = (Q|Outer.Nested|)) [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] T> : R|@R|Special|(why = (#)) Interface| { + @R|Special|[Types](why = (Q|Outer.Nested|)) public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] class Nested<@R|Special|[Types](why = (Q|Outer.Nested|)) [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] T> : R|@R|Special|(why = (Q|Outer.Nested|)) Interface| { public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Nested] constructor<@R|Special|[Types](why = (Q|Outer.Nested|)) [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] T>(): R|Outer.Nested| { LAZY_super<> } @@ -340,7 +340,7 @@ FILE: [ResolvedTo(IMPORTS)] nestedClassAsAnnotationArgument.kt LAZY_super } - @R|Special|[Types](why = (#)) public final [ResolvedTo(BODY_RESOLVE)] class Nested<@R|Special|[Types](why = (Q|Outer.Nested|)) [ResolvedTo(BODY_RESOLVE)] T> : R|@R|Special|(why = (#)) Interface| { + @R|Special|[Types](why = (Q|Outer.Nested|)) public final [ResolvedTo(BODY_RESOLVE)] class Nested<@R|Special|[Types](why = (Q|Outer.Nested|)) [ResolvedTo(BODY_RESOLVE)] T> : R|@R|Special|(why = (Q|Outer.Nested|)) Interface| { public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=Nested] constructor<@R|Special|[Types](why = (Q|Outer.Nested|)) [ResolvedTo(BODY_RESOLVE)] T>(): R|Outer.Nested| { super() } @@ -367,7 +367,7 @@ FILE: [ResolvedTo(BODY_RESOLVE)] nestedClassAsAnnotationArgument.kt super() } - @R|Special|[Types](why = (#)) public final [ResolvedTo(BODY_RESOLVE)] class Nested<@R|Special|[Types](why = (Q|Outer.Nested|)) [ResolvedTo(BODY_RESOLVE)] T> : R|@R|Special|(why = (#)) Interface| { + @R|Special|[Types](why = (Q|Outer.Nested|)) public final [ResolvedTo(BODY_RESOLVE)] class Nested<@R|Special|[Types](why = (Q|Outer.Nested|)) [ResolvedTo(BODY_RESOLVE)] T> : R|@R|Special|(why = (Q|Outer.Nested|)) Interface| { public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=Nested] constructor<@R|Special|[Types](why = (Q|Outer.Nested|)) [ResolvedTo(BODY_RESOLVE)] T>(): R|Outer.Nested| { super() } diff --git a/analysis/low-level-api-fir/testData/lazyResolve/classes/nestedClassAsAnnotationArgument2.txt b/analysis/low-level-api-fir/testData/lazyResolve/classes/nestedClassAsAnnotationArgument2.txt index 2e16225982c..5a10ffcf04e 100644 --- a/analysis/low-level-api-fir/testData/lazyResolve/classes/nestedClassAsAnnotationArgument2.txt +++ b/analysis/low-level-api-fir/testData/lazyResolve/classes/nestedClassAsAnnotationArgument2.txt @@ -313,7 +313,7 @@ FILE: [ResolvedTo(IMPORTS)] nestedClassAsAnnotationArgument2.kt LAZY_super } - @R|Special|[Types](why = #) public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] class Nested<@R|Special|[Types](why = Q|Outer.Nested|) [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] T> : R|@R|Special|(why = #) Interface| { + @R|Special|[Types](why = Q|Outer.Nested|) public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] class Nested<@R|Special|[Types](why = Q|Outer.Nested|) [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] T> : R|@R|Special|(why = Q|Outer.Nested|) Interface| { public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Nested] constructor<@R|Special|[Types](why = Q|Outer.Nested|) [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] T>(): R|Outer.Nested| { LAZY_super<> } @@ -340,7 +340,7 @@ FILE: [ResolvedTo(IMPORTS)] nestedClassAsAnnotationArgument2.kt LAZY_super } - @R|Special|[Types](why = #) public final [ResolvedTo(BODY_RESOLVE)] class Nested<@R|Special|[Types](why = Q|Outer.Nested|) [ResolvedTo(BODY_RESOLVE)] T> : R|@R|Special|(why = #) Interface| { + @R|Special|[Types](why = Q|Outer.Nested|) public final [ResolvedTo(BODY_RESOLVE)] class Nested<@R|Special|[Types](why = Q|Outer.Nested|) [ResolvedTo(BODY_RESOLVE)] T> : R|@R|Special|(why = Q|Outer.Nested|) Interface| { public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=Nested] constructor<@R|Special|[Types](why = Q|Outer.Nested|) [ResolvedTo(BODY_RESOLVE)] T>(): R|Outer.Nested| { super() } @@ -367,7 +367,7 @@ FILE: [ResolvedTo(BODY_RESOLVE)] nestedClassAsAnnotationArgument2.kt super() } - @R|Special|[Types](why = #) public final [ResolvedTo(BODY_RESOLVE)] class Nested<@R|Special|[Types](why = Q|Outer.Nested|) [ResolvedTo(BODY_RESOLVE)] T> : R|@R|Special|(why = #) Interface| { + @R|Special|[Types](why = Q|Outer.Nested|) public final [ResolvedTo(BODY_RESOLVE)] class Nested<@R|Special|[Types](why = Q|Outer.Nested|) [ResolvedTo(BODY_RESOLVE)] T> : R|@R|Special|(why = Q|Outer.Nested|) Interface| { public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=Nested] constructor<@R|Special|[Types](why = Q|Outer.Nested|) [ResolvedTo(BODY_RESOLVE)] T>(): R|Outer.Nested| { super() } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt index 39a7f9ac33c..20f24b76225 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt @@ -90,6 +90,24 @@ class BodyResolveContext( @set:PrivateForInline var inferenceSession: FirInferenceSession = FirInferenceSession.DEFAULT + /** + * This is required to avoid changing current mode into [FirTowerDataMode.CLASS_HEADER_ANNOTATIONS]. + * E.g., we can visit the same annotation in two ways – during a class visiting and outside of this class + */ + @set:PrivateForInline + var insideClassHeader: Boolean = false + + @OptIn(PrivateForInline::class) + inline fun insideClassHeader(action: () -> Unit) { + val old = insideClassHeader + insideClassHeader = true + try { + action() + } finally { + insideClassHeader = old + } + } + /** * CS for an outer type system if it's relevant, for example, in the case of `val x by myGenericDelegateCall()`, * relevant `getValue` call is expected to be resolved in the context of an outer CS built from `myGenericDelegateCall()` and @@ -751,8 +769,8 @@ class BodyResolveContext( inline fun forAnnotation( f: () -> T ): T { - return when (containerIfAny) { - is FirRegularClass -> withTowerDataMode(FirTowerDataMode.CLASS_HEADER_ANNOTATIONS, f) + return when { + containerIfAny is FirRegularClass && !insideClassHeader -> withTowerDataMode(FirTowerDataMode.CLASS_HEADER_ANNOTATIONS, f) else -> f() } } diff --git a/compiler/testData/diagnostics/tests/annotations/constantFromOuterScopeAsAnnotaionParameter.ll.kt b/compiler/testData/diagnostics/tests/annotations/constantFromOuterScopeAsAnnotaionParameter.ll.kt deleted file mode 100644 index cfc04908357..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/constantFromOuterScopeAsAnnotaionParameter.ll.kt +++ /dev/null @@ -1,14 +0,0 @@ -// LL_FIR_DIVERGENCE -// KT-62587 -// LL_FIR_DIVERGENCE -// FIR_IDENTICAL -annotation class Anno(val number: Int) - -class Outer { - companion object { - const val CONSTANT_FROM_COMPANION = 42 - - @Anno(CONSTANT_FROM_COMPANION) - class Nested - } -} diff --git a/compiler/testData/diagnostics/tests/annotations/nestedClassAsAnnotationParameter.ll.kt b/compiler/testData/diagnostics/tests/annotations/nestedClassAsAnnotationParameter.ll.kt deleted file mode 100644 index 8c411b52b0e..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/nestedClassAsAnnotationParameter.ll.kt +++ /dev/null @@ -1,15 +0,0 @@ -// LL_FIR_DIVERGENCE -// KT-62587 -// LL_FIR_DIVERGENCE -// FIR_IDENTICAL -import kotlin.reflect.KClass - -@Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.TYPE) -annotation class Special(val why: KClass<*>) - -interface Interface - -class Outer { - @Special(Nested::class) - class Nested<@Special(Nested::class) T> : @Special(Nested::class) Interface -} diff --git a/compiler/testData/diagnostics/tests/annotations/nestedClassAsIsAsAnnotationParameter.ll.kt b/compiler/testData/diagnostics/tests/annotations/nestedClassAsIsAsAnnotationParameter.ll.kt deleted file mode 100644 index 041d4262185..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/nestedClassAsIsAsAnnotationParameter.ll.kt +++ /dev/null @@ -1,14 +0,0 @@ -// LL_FIR_DIVERGENCE -// KT-62587 -// LL_FIR_DIVERGENCE -import kotlin.reflect.KClass - -@Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.TYPE) -annotation class Special(val why: KClass<*>) - -interface Interface - -class Outer { - @Special(Nested) - class Nested<@Special(Nested) T> : @Special(Nested) Interface -} diff --git a/compiler/testData/diagnostics/tests/annotations/nestedObjectAsAnnotationParameter.ll.kt b/compiler/testData/diagnostics/tests/annotations/nestedObjectAsAnnotationParameter.ll.kt deleted file mode 100644 index 714b4592ce4..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/nestedObjectAsAnnotationParameter.ll.kt +++ /dev/null @@ -1,15 +0,0 @@ -// LL_FIR_DIVERGENCE -// KT-62587 -// LL_FIR_DIVERGENCE -// FIR_IDENTICAL -import kotlin.reflect.KClass - -@Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE) -annotation class Special(val why: KClass<*>) - -interface Interface - -object Outer { - @Special(Nested::class) - object Nested : @Special(Nested::class) Interface -}