[FIR] Enable asserts for not building AST tree in lazy mode

Make interface delegate expressions lazy
This commit is contained in:
Egor Kulikov
2023-05-10 11:49:42 +00:00
committed by Space Team
parent b2fa104081
commit 6f20ac4f38
11 changed files with 107 additions and 89 deletions
@@ -183,6 +183,20 @@ internal object FirLazyBodiesCalculator {
} }
} }
fun calculateLazyBodiesForField(designation: FirDesignation) {
val field = designation.target as FirField
require(field.initializer is FirLazyExpression)
val newField = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
session = field.moduleData.session,
scopeProvider = field.moduleData.session.kotlinScopeProvider,
designation = designation,
rootNonLocalDeclaration = designation.path.last().psi as KtClassOrObject,
) as FirField
field.apply {
replaceInitializer(newField.initializer)
}
}
fun needCalculatingLazyBodyForConstructor(firConstructor: FirConstructor): Boolean = fun needCalculatingLazyBodyForConstructor(firConstructor: FirConstructor): Boolean =
needCalculatingLazyBodyForFunction(firConstructor) || firConstructor.delegatedConstructor is FirLazyDelegatedConstructorCall needCalculatingLazyBodyForFunction(firConstructor) || firConstructor.delegatedConstructor is FirLazyDelegatedConstructorCall
@@ -301,6 +315,14 @@ private object FirLazyBodiesCalculatorTransformer : FirTransformer<PersistentLis
return element return element
} }
override fun transformField(field: FirField, data: PersistentList<FirRegularClass>): FirStatement {
if (field.initializer is FirLazyExpression) {
val designation = FirDesignation(data, field)
FirLazyBodiesCalculator.calculateLazyBodiesForField(designation)
}
return field
}
override fun transformSimpleFunction( override fun transformSimpleFunction(
simpleFunction: FirSimpleFunction, simpleFunction: FirSimpleFunction,
data: PersistentList<FirRegularClass> data: PersistentList<FirRegularClass>
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.name.NameUtils
import org.jetbrains.kotlin.psi import org.jetbrains.kotlin.psi
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
@@ -276,6 +277,22 @@ internal class RawFirNonLocalDeclarationBuilder private constructor(
val selfType = classOrObject.toDelegatedSelfType(typeParameters, owner.symbol) val selfType = classOrObject.toDelegatedSelfType(typeParameters, owner.symbol)
return enumEntry.toFirEnumEntry(selfType, ownerClassHasDefaultConstructor) return enumEntry.toFirEnumEntry(selfType, ownerClassHasDefaultConstructor)
} }
fun processField(classOrObject: KtClassOrObject, originalDeclaration: FirField): FirField? {
var index = 0
classOrObject.superTypeListEntries.forEach { superTypeListEntry ->
if (superTypeListEntry is KtDelegatedSuperTypeEntry) {
val expectedName = NameUtils.delegateFieldName(index)
if (originalDeclaration.name == expectedName) {
return buildFieldForSupertypeDelegate(
superTypeListEntry, superTypeListEntry.typeReference.toFirOrErrorType(), index
)
}
index++
}
}
return null
}
} }
private fun moveNext(iterator: Iterator<FirDeclaration>, containingClass: FirRegularClass?): FirDeclaration { private fun moveNext(iterator: Iterator<FirDeclaration>, containingClass: FirRegularClass?): FirDeclaration {
@@ -296,10 +313,10 @@ internal class RawFirNonLocalDeclarationBuilder private constructor(
} }
} }
is KtClassOrObject -> { is KtClassOrObject -> {
if (originalDeclaration is FirConstructor) { when {
visitor.processPrimaryConstructor(declarationToBuild, null) originalDeclaration is FirConstructor -> visitor.processPrimaryConstructor(declarationToBuild, null)
} else { originalDeclaration is FirField -> visitor.processField(declarationToBuild, originalDeclaration)
visitor.convertElement(declarationToBuild) else -> visitor.convertElement(declarationToBuild)
} }
} }
else -> visitor.convertElement(declarationToBuild) else -> visitor.convertElement(declarationToBuild)
@@ -16,7 +16,7 @@ FILE: [ResolvedTo(RAW_FIR)] delegatedField.kt
LAZY_super<<implicit>> LAZY_super<<implicit>>
} }
private final [ResolvedTo(RAW_FIR)] field $$delegate_0: Foo = prop# private final [ResolvedTo(RAW_FIR)] field $$delegate_0: Foo = LAZY_EXPRESSION
public? final? [ResolvedTo(RAW_FIR)] fun baz([ResolvedTo(RAW_FIR)] s: String): R|kotlin/Unit| { LAZY_BLOCK } public? final? [ResolvedTo(RAW_FIR)] fun baz([ResolvedTo(RAW_FIR)] s: String): R|kotlin/Unit| { LAZY_BLOCK }
@@ -40,7 +40,7 @@ FILE: [ResolvedTo(IMPORTS)] delegatedField.kt
LAZY_super<<implicit>> LAZY_super<<implicit>>
} }
private final [ResolvedTo(RAW_FIR)] field $$delegate_0: Foo = prop# private final [ResolvedTo(RAW_FIR)] field $$delegate_0: Foo = LAZY_EXPRESSION
public? final? [ResolvedTo(RAW_FIR)] fun baz([ResolvedTo(RAW_FIR)] s: String): R|kotlin/Unit| { LAZY_BLOCK } public? final? [ResolvedTo(RAW_FIR)] fun baz([ResolvedTo(RAW_FIR)] s: String): R|kotlin/Unit| { LAZY_BLOCK }
@@ -64,7 +64,7 @@ FILE: [ResolvedTo(IMPORTS)] delegatedField.kt
LAZY_super<<implicit>> LAZY_super<<implicit>>
} }
private final [ResolvedTo(COMPILER_REQUIRED_ANNOTATIONS)] field $$delegate_0: Foo = prop# private final [ResolvedTo(COMPILER_REQUIRED_ANNOTATIONS)] field $$delegate_0: Foo = LAZY_EXPRESSION
public? final? [ResolvedTo(RAW_FIR)] fun baz([ResolvedTo(RAW_FIR)] s: String): R|kotlin/Unit| { LAZY_BLOCK } public? final? [ResolvedTo(RAW_FIR)] fun baz([ResolvedTo(RAW_FIR)] s: String): R|kotlin/Unit| { LAZY_BLOCK }
@@ -88,7 +88,7 @@ FILE: [ResolvedTo(IMPORTS)] delegatedField.kt
LAZY_super<<implicit>> LAZY_super<<implicit>>
} }
private final [ResolvedTo(COMPANION_GENERATION)] field $$delegate_0: Foo = prop# private final [ResolvedTo(COMPANION_GENERATION)] field $$delegate_0: Foo = LAZY_EXPRESSION
public? final? [ResolvedTo(RAW_FIR)] fun baz([ResolvedTo(RAW_FIR)] s: String): R|kotlin/Unit| { LAZY_BLOCK } public? final? [ResolvedTo(RAW_FIR)] fun baz([ResolvedTo(RAW_FIR)] s: String): R|kotlin/Unit| { LAZY_BLOCK }
@@ -112,7 +112,7 @@ FILE: [ResolvedTo(IMPORTS)] delegatedField.kt
LAZY_super<<implicit>> LAZY_super<<implicit>>
} }
private final [ResolvedTo(SUPER_TYPES)] field $$delegate_0: Foo = prop# private final [ResolvedTo(SUPER_TYPES)] field $$delegate_0: Foo = LAZY_EXPRESSION
public? final? [ResolvedTo(RAW_FIR)] fun baz([ResolvedTo(RAW_FIR)] s: String): R|kotlin/Unit| { LAZY_BLOCK } public? final? [ResolvedTo(RAW_FIR)] fun baz([ResolvedTo(RAW_FIR)] s: String): R|kotlin/Unit| { LAZY_BLOCK }
@@ -136,7 +136,7 @@ FILE: [ResolvedTo(IMPORTS)] delegatedField.kt
LAZY_super<<implicit>> LAZY_super<<implicit>>
} }
private final [ResolvedTo(TYPES)] field $$delegate_0: R|one/Foo| = prop# private final [ResolvedTo(TYPES)] field $$delegate_0: R|one/Foo| = LAZY_EXPRESSION
public? final? [ResolvedTo(RAW_FIR)] fun baz([ResolvedTo(RAW_FIR)] s: String): R|kotlin/Unit| { LAZY_BLOCK } public? final? [ResolvedTo(RAW_FIR)] fun baz([ResolvedTo(RAW_FIR)] s: String): R|kotlin/Unit| { LAZY_BLOCK }
@@ -160,7 +160,7 @@ FILE: [ResolvedTo(IMPORTS)] delegatedField.kt
LAZY_super<<implicit>> LAZY_super<<implicit>>
} }
private final [ResolvedTo(STATUS)] field $$delegate_0: R|one/Foo| = prop# private final [ResolvedTo(STATUS)] field $$delegate_0: R|one/Foo| = LAZY_EXPRESSION
public final [ResolvedTo(STATUS)] fun baz([ResolvedTo(STATUS)] s: R|kotlin/String|): R|kotlin/Unit| { LAZY_BLOCK } public final [ResolvedTo(STATUS)] fun baz([ResolvedTo(STATUS)] s: R|kotlin/String|): R|kotlin/Unit| { LAZY_BLOCK }
@@ -184,7 +184,7 @@ FILE: [ResolvedTo(IMPORTS)] delegatedField.kt
LAZY_super<<implicit>> LAZY_super<<implicit>>
} }
private final [ResolvedTo(EXPECT_ACTUAL_MATCHING)] field $$delegate_0: R|one/Foo| = prop# private final [ResolvedTo(EXPECT_ACTUAL_MATCHING)] field $$delegate_0: R|one/Foo| = LAZY_EXPRESSION
public final [ResolvedTo(STATUS)] fun baz([ResolvedTo(STATUS)] s: R|kotlin/String|): R|kotlin/Unit| { LAZY_BLOCK } public final [ResolvedTo(STATUS)] fun baz([ResolvedTo(STATUS)] s: R|kotlin/String|): R|kotlin/Unit| { LAZY_BLOCK }
@@ -208,7 +208,7 @@ FILE: [ResolvedTo(IMPORTS)] delegatedField.kt
LAZY_super<<implicit>> LAZY_super<<implicit>>
} }
private final [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] field $$delegate_0: R|one/Foo| = prop# private final [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] field $$delegate_0: R|one/Foo| = LAZY_EXPRESSION
public final [ResolvedTo(STATUS)] fun baz([ResolvedTo(STATUS)] s: R|kotlin/String|): R|kotlin/Unit| { LAZY_BLOCK } public final [ResolvedTo(STATUS)] fun baz([ResolvedTo(STATUS)] s: R|kotlin/String|): R|kotlin/Unit| { LAZY_BLOCK }
@@ -1881,7 +1881,7 @@ class DeclarationsConverter(
delegateFieldsMap.put( delegateFieldsMap.put(
index, index,
buildField { buildField {
source = calculatedFirExpression.source?.fakeElement(KtFakeSourceElementKind.ClassDelegationField) source = explicitDelegation.toFirSourceElement().fakeElement(KtFakeSourceElementKind.ClassDelegationField)
moduleData = baseModuleData moduleData = baseModuleData
origin = FirDeclarationOrigin.Synthetic origin = FirDeclarationOrigin.Synthetic
name = NameUtils.delegateFieldName(delegateFieldsMap.size) name = NameUtils.delegateFieldName(delegateFieldsMap.size)
@@ -65,16 +65,6 @@ open class RawFirBuilder(
var mode: BodyBuildingMode = bodyBuildingMode var mode: BodyBuildingMode = bodyBuildingMode
private set private set
private inline fun <T> disabledLazyMode(body: () -> T): T {
if (mode != BodyBuildingMode.LAZY_BODIES) return body()
return try {
mode = BodyBuildingMode.NORMAL
body()
} finally {
mode = BodyBuildingMode.LAZY_BODIES
}
}
private inline fun <T> runOnStubs(crossinline body: () -> T): T { private inline fun <T> runOnStubs(crossinline body: () -> T): T {
return when (mode) { return when (mode) {
BodyBuildingMode.NORMAL -> body() BodyBuildingMode.NORMAL -> body()
@@ -85,7 +75,7 @@ open class RawFirBuilder(
} }
fun buildFirFile(file: KtFile): FirFile { fun buildFirFile(file: KtFile): FirFile {
return file.accept(Visitor(), Unit) as FirFile return runOnStubs { file.accept(Visitor(), Unit) as FirFile }
} }
fun buildAnnotationCall(annotation: KtAnnotationEntry): FirAnnotationCall { fun buildAnnotationCall(annotation: KtAnnotationEntry): FirAnnotationCall {
@@ -250,7 +240,7 @@ open class RawFirBuilder(
private fun KtTypeReference?.toFirOrUnitType(): FirTypeRef = private fun KtTypeReference?.toFirOrUnitType(): FirTypeRef =
convertSafe() ?: implicitUnitType convertSafe() ?: implicitUnitType
private fun KtTypeReference?.toFirOrErrorType(): FirTypeRef = protected fun KtTypeReference?.toFirOrErrorType(): FirTypeRef =
convertSafe() ?: buildErrorTypeRef { convertSafe() ?: buildErrorTypeRef {
source = this@toFirOrErrorType?.toFirSourceElement() source = this@toFirOrErrorType?.toFirSourceElement()
diagnostic = ConeSyntaxDiagnostic( diagnostic = ConeSyntaxDiagnostic(
@@ -848,6 +838,27 @@ open class RawFirBuilder(
container.argumentList = argumentList container.argumentList = argumentList
} }
protected fun buildFieldForSupertypeDelegate(entry: KtDelegatedSuperTypeEntry, type: FirTypeRef, fieldOrd: Int): FirField {
val delegateSource = entry.toFirSourceElement(KtFakeSourceElementKind.ClassDelegationField)
val delegateExpression = buildOrLazyExpression(delegateSource) {
{ entry.delegateExpression }
.toFirExpression("Should have delegate")
}
return buildField {
source = delegateSource
moduleData = baseModuleData
origin = FirDeclarationOrigin.Synthetic
name = NameUtils.delegateFieldName(fieldOrd)
returnTypeRef = type
symbol = FirFieldSymbol(CallableId(this@RawFirBuilder.context.currentClassId, name))
isVar = false
status = FirDeclarationStatusImpl(Visibilities.Private, Modality.FINAL)
initializer = delegateExpression
dispatchReceiverType = currentDispatchReceiverType()
}
}
private fun KtClassOrObject.extractSuperTypeListEntriesTo( private fun KtClassOrObject.extractSuperTypeListEntriesTo(
container: FirClassBuilder, container: FirClassBuilder,
delegatedSelfTypeRef: FirTypeRef?, delegatedSelfTypeRef: FirTypeRef?,
@@ -871,23 +882,8 @@ open class RawFirBuilder(
} }
is KtDelegatedSuperTypeEntry -> { is KtDelegatedSuperTypeEntry -> {
val type = superTypeListEntry.typeReference.toFirOrErrorType() val type = superTypeListEntry.typeReference.toFirOrErrorType()
val delegateExpression =
disabledLazyMode { { superTypeListEntry.delegateExpression }.toFirExpression("Should have delegate") }
container.superTypeRefs += type container.superTypeRefs += type
val delegateSource = val delegateField = buildFieldForSupertypeDelegate(superTypeListEntry, type, delegateFieldsMap.size)
superTypeListEntry.delegateExpression?.toFirSourceElement(KtFakeSourceElementKind.ClassDelegationField)
val delegateField = buildField {
source = delegateSource
moduleData = baseModuleData
origin = FirDeclarationOrigin.Synthetic
name = NameUtils.delegateFieldName(delegateFieldsMap.size)
returnTypeRef = type
symbol = FirFieldSymbol(CallableId(this@RawFirBuilder.context.currentClassId, name))
isVar = false
status = FirDeclarationStatusImpl(Visibilities.Private, Modality.FINAL)
initializer = delegateExpression
dispatchReceiverType = currentDispatchReceiverType()
}
delegateFieldsMap[index] = delegateField.symbol delegateFieldsMap[index] = delegateField.symbol
} }
} }
@@ -983,7 +979,7 @@ open class RawFirBuilder(
?: this@buildDelegatedConstructorCall.source?.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall) ?: this@buildDelegatedConstructorCall.source?.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall)
superTypeRef = this@buildDelegatedConstructorCall.constructedTypeRef superTypeRef = this@buildDelegatedConstructorCall.constructedTypeRef
} }
disabledLazyMode { superTypeCallEntry?.extractArgumentsTo(this) } superTypeCallEntry?.extractArgumentsTo(this)
} }
} }
} }
@@ -1726,7 +1722,7 @@ open class RawFirBuilder(
this.superTypeRef = this@buildDelegatedConstructorCall.constructedTypeRef this.superTypeRef = this@buildDelegatedConstructorCall.constructedTypeRef
} }
} }
disabledLazyMode { extractArgumentsTo(this) } extractArgumentsTo(this)
} }
} }
@@ -11,3 +11,9 @@ val delegate = object: ReadWriteProperty<Any?, Int> {
val value by delegate val value by delegate
var variable by delegate var variable by delegate
interface Base {
}
class Derived(b: Base) : Base by b {
}
@@ -16,3 +16,13 @@ FILE: delegates.kt
public? set(<set-?>: <implicit>): R|kotlin/Unit| { public? set(<set-?>: <implicit>): R|kotlin/Unit| {
D|/variable|.setValue#(Null(null), ::R|/variable|, R|<local>/variable|) D|/variable|.setValue#(Null(null), ::R|/variable|, R|<local>/variable|)
} }
public? final? interface Base : R|kotlin/Any| {
}
public? final? class Derived : Base {
public? constructor(b: Base): R|Derived| {
LAZY_super<<implicit>>
}
private final field $$delegate_0: Base = LAZY_EXPRESSION
}
@@ -32,3 +32,13 @@ FILE: delegates.kt
public? set(<set-?>: <implicit>): R|kotlin/Unit| { public? set(<set-?>: <implicit>): R|kotlin/Unit| {
D|/variable|.setValue#(Null(null), ::R|/variable|, R|<local>/variable|) D|/variable|.setValue#(Null(null), ::R|/variable|, R|<local>/variable|)
} }
public? final? interface Base : R|kotlin/Any| {
}
public? final? [DelegateFieldsMapKey={0=FirFieldSymbol /Derived.$$delegate_0}] class Derived : Base {
public? [ContainingClassKey=Derived] constructor(b: Base): R|Derived| {
super<<implicit>>()
}
private final field $$delegate_0: Base = b#
}
@@ -4,5 +4,5 @@ interface T
annotation class Ann: <!SUPERTYPES_FOR_ANNOTATION_CLASS!>C()<!> annotation class Ann: <!SUPERTYPES_FOR_ANNOTATION_CLASS!>C()<!>
annotation class Ann2: <!SUPERTYPES_FOR_ANNOTATION_CLASS!>T<!> annotation class Ann2: <!SUPERTYPES_FOR_ANNOTATION_CLASS!>T<!>
annotation class Ann3: <!SUPERTYPES_FOR_ANNOTATION_CLASS!>T by <!ANNOTATION_CLASS_MEMBER!>a<!><!> annotation class Ann3: <!ANNOTATION_CLASS_MEMBER, SUPERTYPES_FOR_ANNOTATION_CLASS!>T by a<!>
annotation class Ann4: <!SUPERTYPES_FOR_ANNOTATION_CLASS!>C(), T<!> annotation class Ann4: <!SUPERTYPES_FOR_ANNOTATION_CLASS!>C(), T<!>
@@ -1,44 +0,0 @@
// FIR_DISABLE_LAZY_RESOLVE_CHECKS
// !API_VERSION: 1.5
// !LANGUAGE: +JvmRecordSupport
// SKIP_TXT
// JVM_TARGET: 17
// ENABLE_JVM_PREVIEW
interface I
val i: I = object : I {}
@JvmRecord
data class MyRec1(val name: String) : I by <!DELEGATION_BY_IN_JVM_RECORD!>i<!>
@JvmRecord
data class MyRec2(val name: String) {
<!FIELD_IN_JVM_RECORD!>val x: Int = 0<!>
}
@JvmRecord
data class MyRec3(val name: String) {
<!FIELD_IN_JVM_RECORD!>val y: String
get() = field + "1"<!>
init {
y = ""
}
}
@JvmRecord
data class MyRec4(val name: String) {
<!FIELD_IN_JVM_RECORD!>val z: Int by lazy { 1 }<!>
}
@JvmRecord
data class MyRec5(val name: String) {
val w: String get() = name + "1"
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FIR_DISABLE_LAZY_RESOLVE_CHECKS // FIR_DISABLE_LAZY_RESOLVE_CHECKS
// !API_VERSION: 1.5 // !API_VERSION: 1.5
// !LANGUAGE: +JvmRecordSupport // !LANGUAGE: +JvmRecordSupport