[FIR] make script destructuring declaration initializer lazy expression

This change is required to properly support such declarations in lazy
resolution mode as we usually replaced initializers with lazy
expressions during the body calculation phase

^KT-62840
This commit is contained in:
Dmitrii Gridin
2024-02-09 19:07:05 +01:00
committed by Space Team
parent 898c8c002e
commit 9ca0bdcb80
5 changed files with 40 additions and 21 deletions
@@ -146,10 +146,17 @@ internal class RawFirNonLocalDeclarationBuilder private constructor(
}
private inner class VisitorWithReplacement(private val containingClass: FirRegularClass?) : Visitor() {
fun convertDestructuringDeclaration(element: KtDestructuringDeclaration): FirVariable {
fun convertDestructuringDeclaration(element: KtDestructuringDeclaration, containingDeclaration: FirDeclaration?): FirVariable {
val replacementDeclaration = replacementApplier?.tryReplace(element) ?: element
requireIsInstance<KtDestructuringDeclaration>(replacementDeclaration)
return buildErrorTopLevelDestructuringDeclaration(replacementDeclaration.toFirSourceElement())
return if (containingDeclaration is FirScript) {
withContainerSymbol(containingDeclaration.symbol) {
// Annotations from script destructuring declarations are linked to the script itself
buildScriptDestructuringDeclaration(replacementDeclaration)
}
} else {
buildErrorTopLevelDestructuringDeclaration(replacementDeclaration.toFirSourceElement())
}
}
fun convertAnonymousInitializer(element: KtAnonymousInitializer, containingDeclaration: FirDeclaration?): FirAnonymousInitializer {
@@ -348,7 +355,7 @@ internal class RawFirNonLocalDeclarationBuilder private constructor(
else -> visitor.convertElement(declarationToBuild, originalDeclaration)
}
}
is KtDestructuringDeclaration -> visitor.convertDestructuringDeclaration(declarationToBuild)
is KtDestructuringDeclaration -> visitor.convertDestructuringDeclaration(declarationToBuild, containingDeclaration)
is KtCodeFragment -> {
val firFile = visitor.convertElement(declarationToBuild, originalDeclaration) as FirFile
firFile.codeFragment
@@ -359,7 +366,7 @@ internal class RawFirNonLocalDeclarationBuilder private constructor(
}
val parent = iterator.next()
if (parent !is FirRegularClass) return moveNext(iterator, containingDeclaration = null)
if (parent !is FirRegularClass) return moveNext(iterator, containingDeclaration = parent)
val classOrObject = parent.psi
if (classOrObject !is KtClassOrObject) {
@@ -3,7 +3,7 @@ FIR element: FirPropertyImpl
FIR source kind: KtRealSourceElementKind
FIR element rendered:
[ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableMarkerKey=true] lval <destruct>: <implicit> = ERROR_EXPR(Initializer required for destructuring declaration)
[ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableMarkerKey=true] lval <destruct>: <implicit> = LAZY_EXPRESSION
FIR FILE:
FILE: [ResolvedTo(IMPORTS)] destructionWithNoRValueScript.kts
@@ -11,7 +11,7 @@ FILE: [ResolvedTo(IMPORTS)] destructionWithNoRValueScript.kts
SCRIPT: [ResolvedTo(RAW_FIR)] <script-destructionWithNoRValueScript.kts>
[ResolvedTo(RAW_FIR)] lval args: R|kotlin/Array<kotlin/String>|
[ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableMarkerKey=true] lval <destruct>: <implicit> = ERROR_EXPR(Initializer required for destructuring declaration)
[ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableMarkerKey=true] lval <destruct>: <implicit> = LAZY_EXPRESSION
public final [ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableKey=<local>/<destruct>] val o: <implicit> = R|<local>/<destruct>|.component1#()
@@ -3,7 +3,7 @@ FIR element: FirPropertyImpl
FIR source kind: KtRealSourceElementKind
FIR element rendered:
[ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableMarkerKey=true] lval <destruct>: <implicit> = pair#
[ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableMarkerKey=true] lval <destruct>: <implicit> = LAZY_EXPRESSION
FIR FILE:
FILE: [ResolvedTo(IMPORTS)] destructuringScript.kts
@@ -22,7 +22,7 @@ FILE: [ResolvedTo(IMPORTS)] destructuringScript.kts
public? final? [ResolvedTo(RAW_FIR)] val pair: <implicit> = LAZY_EXPRESSION
public? [ResolvedTo(RAW_FIR)] get(): <implicit>
[ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableMarkerKey=true] lval <destruct>: <implicit> = pair#
[ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableMarkerKey=true] lval <destruct>: <implicit> = LAZY_EXPRESSION
public final [ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableKey=<local>/<destruct>] val first: <implicit> = R|<local>/<destruct>|.component1#()
@@ -1280,6 +1280,26 @@ open class PsiRawFirBuilder(
}
}
protected fun buildScriptDestructuringDeclaration(destructuringDeclaration: KtDestructuringDeclaration): FirVariable {
val initializer = destructuringDeclaration.initializer
val firInitializer = buildOrLazyExpression(initializer?.toFirSourceElement()) {
initializer.toFirExpression { ConeSyntaxDiagnostic("Initializer required for destructuring declaration") }
}
val destructuringContainerVar = generateTemporaryVariable(
moduleData = baseModuleData,
source = destructuringDeclaration.toFirSourceElement(),
specialName = "destruct",
initializer = firInitializer,
origin = FirDeclarationOrigin.Synthetic.ScriptTopLevelDestructuringDeclarationContainer,
extractAnnotationsTo = { extractAnnotationsTo(it) },
).apply {
isDestructuringDeclarationContainerVariable = true
}
return destructuringContainerVar
}
private fun convertScript(
script: KtScript,
fileName: String,
@@ -1301,7 +1321,6 @@ open class PsiRawFirBuilder(
while (scriptDeclarationsIter.hasNext()) {
val declaration = scriptDeclarationsIter.next()
val isLast = !scriptDeclarationsIter.hasNext()
val declarationSource = declaration.toFirSourceElement()
when (declaration) {
is KtScriptInitializer -> {
val initializer = buildAnonymousInitializer(
@@ -1315,16 +1334,7 @@ open class PsiRawFirBuilder(
declarations.add(initializer)
}
is KtDestructuringDeclaration -> {
val destructuringContainerVar = generateTemporaryVariable(
baseModuleData,
declarationSource,
"destruct",
declaration.initializer.toFirExpression { ConeSyntaxDiagnostic("Initializer required for destructuring declaration") },
origin = FirDeclarationOrigin.Synthetic.ScriptTopLevelDestructuringDeclarationContainer,
extractAnnotationsTo = { extractAnnotationsTo(it) }
).apply {
isDestructuringDeclarationContainerVariable = true
}
val destructuringContainerVar = buildScriptDestructuringDeclaration(declaration)
declarations.add(destructuringContainerVar)
declarations.addDestructuringVariables(
@@ -1,15 +1,17 @@
FILE: scriptLevelDestructuringWithAnnotation.kts
SCRIPT: <script-scriptLevelDestructuringWithAnnotation.kts>
@DestrAnno(LAZY_EXPRESSION) lval <destruct>: <implicit> = IntegerLiteral(0).to#(IntegerLiteral(1))
@DestrAnno(LAZY_EXPRESSION) lval <destruct>: <implicit> = LAZY_EXPRESSION
@LeftAnno(LAZY_EXPRESSION) public final val a: <implicit> = R|<local>/<destruct>|.component1#()
@RightAnno(LAZY_EXPRESSION) public final val b: <implicit> = R|<local>/<destruct>|.component2#()
@Destr2Anno(LAZY_EXPRESSION) lval <destruct>: <implicit> = IntegerLiteral(2).to#(IntegerLiteral(3))
@Destr2Anno(LAZY_EXPRESSION) lval <destruct>: <implicit> = LAZY_EXPRESSION
@SecondLeftAnno(LAZY_EXPRESSION) public final val c: <implicit> = R|<local>/<destruct>|.component1#()
@SecondRightAnno(LAZY_EXPRESSION) public final val d: <implicit> = R|<local>/<destruct>|.component2#()