[FIR] do not transform propagated annotations from place other than declaration side

We shouldn't transform annotations not from declaration side due to
a possible different context and to avoid unexpected transformation of
unrelated declarations

Example:
```kotlin
fun implicitType1() = TopLevelObject.expectedType()

object TopLevelObject {
    private const val privateConstVal = "privateConstVal"
    fun expectedType(): @Anno(privateConstVal) Int = 4
}
```
Here we will try to transform the annotation from `expectedType`
during `implicitType1` and as the result, we will see unresolved
reference on the declaration side. This commit fixes this issue.

This solution is based on the fact that the compiler anyway will
resolve the propagated annotation on the declaration side.
And it doesn't matter if it is resolved before or after the call site
declaration transformation, because as a global result, we will observe
that all declarations are resolved correctly in the right context.

Hence, this commit fixes the issue in the case of "full resolution"
which is true for the compiler, but it is not correct for Low Level
FIR where we resolve declarations on demand. It will be solved in
the next commits

^KT-63042
This commit is contained in:
Dmitrii Gridin
2023-12-01 13:29:09 +01:00
committed by Space Team
parent 6f0d52f991
commit 9888cbbfcd
98 changed files with 1768 additions and 1754 deletions
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.resolve.dfa.DataFlowAnalyzerContext
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve
import org.jetbrains.kotlin.fir.resolve.transformers.ScopeClassDeclaration
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirTransformer
@@ -309,14 +310,31 @@ abstract class FirAbstractBodyResolveTransformerDispatcher(
FirExpressionsResolveTransformer::transformAnnotation,
)
/**
* @param symbol an owner of [annotationCall]
* @param annotationCall an annotation call which does not belong to any declarations on the stack
*
* @see FirAnnotationCall.containingDeclarationSymbol
*/
open fun transformForeignAnnotationCall(symbol: FirBasedSymbol<*>, annotationCall: FirAnnotationCall): FirAnnotationCall {
return annotationCall
}
override fun transformAnnotationCall(
annotationCall: FirAnnotationCall,
data: ResolutionMode,
): FirStatement = expressionTransformation(
annotationCall,
data,
FirExpressionsResolveTransformer::transformAnnotationCall,
)
): FirStatement {
val declarationSymbol = annotationCall.containingDeclarationSymbol
if (declarationSymbol.fir !in context.containers.asReversed()) {
return transformForeignAnnotationCall(declarationSymbol, annotationCall)
}
return expressionTransformation(
annotationCall,
data,
FirExpressionsResolveTransformer::transformAnnotationCall,
)
}
override fun transformErrorAnnotationCall(
errorAnnotationCall: FirErrorAnnotationCall,
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.resolve.FirRegularTowerDataContexts
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession
@@ -24,6 +25,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFull
import org.jetbrains.kotlin.fir.resolve.transformers.contracts.runContractResolveForLocalClass
import org.jetbrains.kotlin.fir.scopes.CallableCopyTypeCalculator
import org.jetbrains.kotlin.fir.scopes.impl.originalForWrappedIntegerOperator
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirSyntheticPropertySymbol
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
@@ -127,6 +129,11 @@ open class FirImplicitAwareBodyResolveTransformer(
outerBodyResolveContext,
firResolveContextCollector
) {
override fun transformForeignAnnotationCall(symbol: FirBasedSymbol<*>, annotationCall: FirAnnotationCall): FirAnnotationCall {
val outerTransformer = (returnTypeCalculator as ReturnTypeCalculatorWithJump).outerTransformer
return outerTransformer?.transformForeignAnnotationCall(symbol, annotationCall) ?: annotationCall
}
/**
* This is required to avoid transformations of class annotations
*/
@@ -1,14 +0,0 @@
package usage
@Target(AnnotationTarget.TYPE)
annotation class Anno(val s: String)
fun implicitType1() = TopLevelObject.expectedType()
object TopLevelObject {
fun expectedType2(): @Anno(privateConstVal) Int = 4
private const val privateConstVal = "privateConstVal"
fun expectedType(): @Anno(<!UNRESOLVED_REFERENCE!>privateConstVal<!>) Int = 4
}
fun implicitType2() = TopLevelObject.expectedType2()
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
package usage
@Target(AnnotationTarget.TYPE)
@@ -1,14 +0,0 @@
package usage
@Target(AnnotationTarget.TYPE)
annotation class Anno(val s: String)
fun implicitType1() = TopLevelObject.expectedType()
object TopLevelObject {
fun expectedType2(): @Anno(<!UNRESOLVED_REFERENCE!>privateConstVal<!>) Int = 4
private const val privateConstVal = "privateConstVal"
fun expectedType(): @Anno(privateConstVal) Int = 4
}
fun implicitType2() = TopLevelObject.expectedType2()