diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/FirLazyBodiesCalculator.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/FirLazyBodiesCalculator.kt index 22ad88a3253..e7762970cd7 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/FirLazyBodiesCalculator.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/FirLazyBodiesCalculator.kt @@ -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 = needCalculatingLazyBodyForFunction(firConstructor) || firConstructor.delegatedConstructor is FirLazyDelegatedConstructorCall @@ -301,6 +315,14 @@ private object FirLazyBodiesCalculatorTransformer : FirTransformer): FirStatement { + if (field.initializer is FirLazyExpression) { + val designation = FirDesignation(data, field) + FirLazyBodiesCalculator.calculateLazyBodiesForField(designation) + } + return field + } + override fun transformSimpleFunction( simpleFunction: FirSimpleFunction, data: PersistentList diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirNonLocalDeclarationBuilder.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirNonLocalDeclarationBuilder.kt index 99ab207b446..95917e1e73b 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirNonLocalDeclarationBuilder.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirNonLocalDeclarationBuilder.kt @@ -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.types.FirResolvedTypeRef 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.psiUtil.hasExpectModifier @@ -276,6 +277,22 @@ internal class RawFirNonLocalDeclarationBuilder private constructor( val selfType = classOrObject.toDelegatedSelfType(typeParameters, owner.symbol) 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, containingClass: FirRegularClass?): FirDeclaration { @@ -296,10 +313,10 @@ internal class RawFirNonLocalDeclarationBuilder private constructor( } } is KtClassOrObject -> { - if (originalDeclaration is FirConstructor) { - visitor.processPrimaryConstructor(declarationToBuild, null) - } else { - visitor.convertElement(declarationToBuild) + when { + originalDeclaration is FirConstructor -> visitor.processPrimaryConstructor(declarationToBuild, null) + originalDeclaration is FirField -> visitor.processField(declarationToBuild, originalDeclaration) + else -> visitor.convertElement(declarationToBuild) } } else -> visitor.convertElement(declarationToBuild) diff --git a/analysis/low-level-api-fir/testdata/lazyResolve/delegatedField.txt b/analysis/low-level-api-fir/testdata/lazyResolve/delegatedField.txt index c236081da43..ae756d9e632 100644 --- a/analysis/low-level-api-fir/testdata/lazyResolve/delegatedField.txt +++ b/analysis/low-level-api-fir/testdata/lazyResolve/delegatedField.txt @@ -16,7 +16,7 @@ FILE: [ResolvedTo(RAW_FIR)] delegatedField.kt LAZY_super<> } - 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 } @@ -40,7 +40,7 @@ FILE: [ResolvedTo(IMPORTS)] delegatedField.kt LAZY_super<> } - 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 } @@ -64,7 +64,7 @@ FILE: [ResolvedTo(IMPORTS)] delegatedField.kt LAZY_super<> } - 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 } @@ -88,7 +88,7 @@ FILE: [ResolvedTo(IMPORTS)] delegatedField.kt LAZY_super<> } - 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 } @@ -112,7 +112,7 @@ FILE: [ResolvedTo(IMPORTS)] delegatedField.kt LAZY_super<> } - 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 } @@ -136,7 +136,7 @@ FILE: [ResolvedTo(IMPORTS)] delegatedField.kt LAZY_super<> } - 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 } @@ -160,7 +160,7 @@ FILE: [ResolvedTo(IMPORTS)] delegatedField.kt LAZY_super<> } - 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 } @@ -184,7 +184,7 @@ FILE: [ResolvedTo(IMPORTS)] delegatedField.kt LAZY_super<> } - 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 } @@ -208,7 +208,7 @@ FILE: [ResolvedTo(IMPORTS)] delegatedField.kt LAZY_super<> } - 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 } diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt index ae52f8d5042..4f00008f1bb 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt @@ -1881,7 +1881,7 @@ class DeclarationsConverter( delegateFieldsMap.put( index, buildField { - source = calculatedFirExpression.source?.fakeElement(KtFakeSourceElementKind.ClassDelegationField) + source = explicitDelegation.toFirSourceElement().fakeElement(KtFakeSourceElementKind.ClassDelegationField) moduleData = baseModuleData origin = FirDeclarationOrigin.Synthetic name = NameUtils.delegateFieldName(delegateFieldsMap.size) diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index a67a949ac66..6e1b1a44be7 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -65,16 +65,6 @@ open class RawFirBuilder( var mode: BodyBuildingMode = bodyBuildingMode private set - private inline fun 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 runOnStubs(crossinline body: () -> T): T { return when (mode) { BodyBuildingMode.NORMAL -> body() @@ -85,7 +75,7 @@ open class RawFirBuilder( } 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 { @@ -250,7 +240,7 @@ open class RawFirBuilder( private fun KtTypeReference?.toFirOrUnitType(): FirTypeRef = convertSafe() ?: implicitUnitType - private fun KtTypeReference?.toFirOrErrorType(): FirTypeRef = + protected fun KtTypeReference?.toFirOrErrorType(): FirTypeRef = convertSafe() ?: buildErrorTypeRef { source = this@toFirOrErrorType?.toFirSourceElement() diagnostic = ConeSyntaxDiagnostic( @@ -848,6 +838,27 @@ open class RawFirBuilder( 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( container: FirClassBuilder, delegatedSelfTypeRef: FirTypeRef?, @@ -871,23 +882,8 @@ open class RawFirBuilder( } is KtDelegatedSuperTypeEntry -> { val type = superTypeListEntry.typeReference.toFirOrErrorType() - val delegateExpression = - disabledLazyMode { { superTypeListEntry.delegateExpression }.toFirExpression("Should have delegate") } container.superTypeRefs += type - val delegateSource = - 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() - } + val delegateField = buildFieldForSupertypeDelegate(superTypeListEntry, type, delegateFieldsMap.size) delegateFieldsMap[index] = delegateField.symbol } } @@ -983,7 +979,7 @@ open class RawFirBuilder( ?: this@buildDelegatedConstructorCall.source?.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall) superTypeRef = this@buildDelegatedConstructorCall.constructedTypeRef } - disabledLazyMode { superTypeCallEntry?.extractArgumentsTo(this) } + superTypeCallEntry?.extractArgumentsTo(this) } } } @@ -1726,7 +1722,7 @@ open class RawFirBuilder( this.superTypeRef = this@buildDelegatedConstructorCall.constructedTypeRef } } - disabledLazyMode { extractArgumentsTo(this) } + extractArgumentsTo(this) } } diff --git a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.kt b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.kt index 1fe6e7121c8..589864a9cda 100644 --- a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.kt +++ b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.kt @@ -11,3 +11,9 @@ val delegate = object: ReadWriteProperty { val value by delegate var variable by delegate + +interface Base { +} + +class Derived(b: Base) : Base by b { +} diff --git a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.lazyBodies.txt b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.lazyBodies.txt index 1e06ed88f37..e038c6941d6 100644 --- a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.lazyBodies.txt +++ b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.lazyBodies.txt @@ -16,3 +16,13 @@ FILE: delegates.kt public? set(: ): R|kotlin/Unit| { D|/variable|.setValue#(Null(null), ::R|/variable|, R|/variable|) } + public? final? interface Base : R|kotlin/Any| { + } + public? final? class Derived : Base { + public? constructor(b: Base): R|Derived| { + LAZY_super<> + } + + private final field $$delegate_0: Base = LAZY_EXPRESSION + + } diff --git a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.txt b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.txt index 70c17443e68..8fa20779f63 100644 --- a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.txt +++ b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.txt @@ -32,3 +32,13 @@ FILE: delegates.kt public? set(: ): R|kotlin/Unit| { D|/variable|.setValue#(Null(null), ::R|/variable|, R|/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<>() + } + + private final field $$delegate_0: Base = b# + + } diff --git a/compiler/testData/diagnostics/tests/annotations/annotationInheritance.fir.kt b/compiler/testData/diagnostics/tests/annotations/annotationInheritance.fir.kt index 56833c94cb0..5eb6b979b32 100644 --- a/compiler/testData/diagnostics/tests/annotations/annotationInheritance.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/annotationInheritance.fir.kt @@ -4,5 +4,5 @@ interface T annotation class Ann: C() annotation class Ann2: T -annotation class Ann3: T by a +annotation class Ann3: T by a annotation class Ann4: C(), T diff --git a/compiler/testData/diagnostics/tests/testsWithJava17/jvmRecord/irrelevantFields.fir.kt b/compiler/testData/diagnostics/tests/testsWithJava17/jvmRecord/irrelevantFields.fir.kt deleted file mode 100644 index 41c04e6be89..00000000000 --- a/compiler/testData/diagnostics/tests/testsWithJava17/jvmRecord/irrelevantFields.fir.kt +++ /dev/null @@ -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 i - -@JvmRecord -data class MyRec2(val name: String) { - val x: Int = 0 -} - -@JvmRecord -data class MyRec3(val name: String) { - val y: String - get() = field + "1" - - init { - y = "" - } -} - -@JvmRecord -data class MyRec4(val name: String) { - val z: Int by lazy { 1 } -} - -@JvmRecord -data class MyRec5(val name: String) { - val w: String get() = name + "1" -} - - - - - - diff --git a/compiler/testData/diagnostics/tests/testsWithJava17/jvmRecord/irrelevantFields.kt b/compiler/testData/diagnostics/tests/testsWithJava17/jvmRecord/irrelevantFields.kt index 4bb6f0f1310..4d6c36c5e6e 100644 --- a/compiler/testData/diagnostics/tests/testsWithJava17/jvmRecord/irrelevantFields.kt +++ b/compiler/testData/diagnostics/tests/testsWithJava17/jvmRecord/irrelevantFields.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // FIR_DISABLE_LAZY_RESOLVE_CHECKS // !API_VERSION: 1.5 // !LANGUAGE: +JvmRecordSupport