From 21fff5634ebb03c21b251f524876debbc692126e Mon Sep 17 00:00:00 2001 From: Nikita Bobko Date: Tue, 6 Feb 2024 15:53:04 +0100 Subject: [PATCH] [FIR] Fir modality of FirPropertyAccessor ^KT-61798 Fixed Review: https://jetbrains.team/p/kt/reviews/14230/timeline Q: How resolved modality of an accessor affects expect/actual matching algorithm of properties? A: It's not expect/actual matching of properties, but expect/actual matching of properties setter. Declarations (setters in our case) in actual are allowed to have wider visibility but only if the appropriate expect is `final`. Before this commit, all property accessors were always `final` by mistake. After this commit, they have the modality derived from their containingProperty. Related problem: PositionStrategy for ACTUAL_WITHOUT_EXPECT can be improved KT-65720 The fix in `resolveModality` is similar to how `resolveVisibility` works Related tests: - ConfigurationCacheForAndroidIT.testKotlinAndroidProject - FirIdeNormalAnalysisSourceModuleCombinedDeclaredMemberScopeTestGenerated.testEnumClassWithAbstractMembers - FirIdeNormalAnalysisSourceModuleCombinedDeclaredMemberScopeTestGenerated.testEnumEntryInitializerWithOverriddenMember - FirIdeNormalAnalysisSourceModuleDeclaredMemberScopeTestGenerated.testDelegateInterfaceLibrary - FirIdeNormalAnalysisSourceModuleDeclaredMemberScopeTestGenerated.testEnumClassWithAbstractMembers - FirIdeNormalAnalysisSourceModuleDeclaredMemberScopeTestGenerated.testEnumEntryInitializerWithOverriddenMember - FirIdeNormalAnalysisSourceModuleMemberScopeTestGenerated.testEnumClassWithAbstractMembers - FirIdeNormalAnalysisSourceModuleMemberScopeTestGenerated.testEnumEntryInitializerWithOverriddenMember - FirIdeNormalAnalysisSourceModuleSymbolByPsiTestGenerated.testEnumEntryOverride - FirIdeNormalAnalysisSourceModuleSymbolByPsiTestGenerated.testEnumValueMember - FirStandaloneNormalAnalysisSourceModuleCombinedDeclaredMemberScopeTestGenerated.testEnumClassWithAbstractMembers - FirStandaloneNormalAnalysisSourceModuleCombinedDeclaredMemberScopeTestGenerated.testEnumEntryInitializerWithOverriddenMember - FirStandaloneNormalAnalysisSourceModuleDeclaredMemberScopeTestGenerated.testEnumClassWithAbstractMembers - FirStandaloneNormalAnalysisSourceModuleDeclaredMemberScopeTestGenerated.testEnumEntryInitializerWithOverriddenMember - FirStandaloneNormalAnalysisSourceModuleMemberScopeTestGenerated.testEnumClassWithAbstractMembers - FirStandaloneNormalAnalysisSourceModuleMemberScopeTestGenerated.testEnumEntryInitializerWithOverriddenMember - DiagnosticCompilerTestFE10TestdataTestGenerated*testChangeSetterVisibilityInOverride --- .../enumClassWithAbstractMembers.txt | 2 +- .../enumEntryInitializerWithOverriddenMember.txt | 2 +- .../declaredMemberScope/delegateInterfaceLibrary.txt | 12 ++++++------ .../enumClassWithAbstractMembers.txt | 2 +- .../enumEntryInitializerWithOverriddenMember.txt | 2 +- .../memberScope/enumClassWithAbstractMembers.txt | 2 +- .../enumEntryInitializerWithOverriddenMember.txt | 2 +- .../symbols/symbolByPsi/enumEntryOverride.txt | 4 ++-- .../testData/symbols/symbolByPsi/enumValueMember.txt | 4 ++-- .../fir/resolve/transformers/FirStatusResolver.kt | 10 +++++----- .../changeSetterVisibilityInOverride.fir.kt | 2 +- .../changeSetterVisibilityInOverride.ll.kt | 2 +- .../stubs/genericClassInDifferentModule.fir.ir.txt | 8 ++++---- 13 files changed, 27 insertions(+), 27 deletions(-) diff --git a/analysis/analysis-api/testData/components/scopeProvider/combinedDeclaredMemberScope/enumClassWithAbstractMembers.txt b/analysis/analysis-api/testData/components/scopeProvider/combinedDeclaredMemberScope/enumClassWithAbstractMembers.txt index 347ec1c23de..b575576c7b1 100644 --- a/analysis/analysis-api/testData/components/scopeProvider/combinedDeclaredMemberScope/enumClassWithAbstractMembers.txt +++ b/analysis/analysis-api/testData/components/scopeProvider/combinedDeclaredMemberScope/enumClassWithAbstractMembers.txt @@ -73,7 +73,7 @@ KtKotlinPropertySymbol: isExtension: false isInline: false isOverride: false - modality: FINAL + modality: ABSTRACT origin: SOURCE receiverParameter: null returnType: KtUsualClassType: diff --git a/analysis/analysis-api/testData/components/scopeProvider/combinedDeclaredMemberScope/enumEntryInitializerWithOverriddenMember.txt b/analysis/analysis-api/testData/components/scopeProvider/combinedDeclaredMemberScope/enumEntryInitializerWithOverriddenMember.txt index 57f58284100..082166e0e31 100644 --- a/analysis/analysis-api/testData/components/scopeProvider/combinedDeclaredMemberScope/enumEntryInitializerWithOverriddenMember.txt +++ b/analysis/analysis-api/testData/components/scopeProvider/combinedDeclaredMemberScope/enumEntryInitializerWithOverriddenMember.txt @@ -31,7 +31,7 @@ KtKotlinPropertySymbol: isExtension: false isInline: false isOverride: true - modality: FINAL + modality: OPEN origin: SOURCE receiverParameter: null returnType: KtUsualClassType: diff --git a/analysis/analysis-api/testData/components/scopeProvider/declaredMemberScope/delegateInterfaceLibrary.txt b/analysis/analysis-api/testData/components/scopeProvider/declaredMemberScope/delegateInterfaceLibrary.txt index 1b8f506bb18..44f0b528628 100644 --- a/analysis/analysis-api/testData/components/scopeProvider/declaredMemberScope/delegateInterfaceLibrary.txt +++ b/analysis/analysis-api/testData/components/scopeProvider/declaredMemberScope/delegateInterfaceLibrary.txt @@ -122,7 +122,7 @@ KtKotlinPropertySymbol: isExtension: false isInline: false isOverride: false - modality: FINAL + modality: OPEN origin: SOURCE receiverParameter: null returnType: KtUsualClassType: @@ -173,7 +173,7 @@ KtKotlinPropertySymbol: isExtension: false isInline: false isOverride: false - modality: FINAL + modality: OPEN origin: SOURCE parameter: KtValueParameterSymbol: annotationsList: [] @@ -290,7 +290,7 @@ KtKotlinPropertySymbol: isExtension: false isInline: false isOverride: false - modality: FINAL + modality: OPEN origin: SOURCE receiverParameter: KtReceiverParameterSymbol: annotationsList: [] @@ -439,7 +439,7 @@ KtKotlinPropertySymbol: isExtension: false isInline: false isOverride: false - modality: FINAL + modality: OPEN origin: SOURCE receiverParameter: null returnType: KtUsualClassType: @@ -530,7 +530,7 @@ KtKotlinPropertySymbol: isExtension: false isInline: false isOverride: false - modality: FINAL + modality: OPEN origin: SOURCE receiverParameter: KtReceiverParameterSymbol: annotationsList: [] @@ -601,7 +601,7 @@ KtKotlinPropertySymbol: isExtension: false isInline: false isOverride: false - modality: FINAL + modality: OPEN origin: SOURCE parameter: KtValueParameterSymbol: annotationsList: [] diff --git a/analysis/analysis-api/testData/components/scopeProvider/declaredMemberScope/enumClassWithAbstractMembers.txt b/analysis/analysis-api/testData/components/scopeProvider/declaredMemberScope/enumClassWithAbstractMembers.txt index dabc230ca9f..6ba30d40aaf 100644 --- a/analysis/analysis-api/testData/components/scopeProvider/declaredMemberScope/enumClassWithAbstractMembers.txt +++ b/analysis/analysis-api/testData/components/scopeProvider/declaredMemberScope/enumClassWithAbstractMembers.txt @@ -31,7 +31,7 @@ KtKotlinPropertySymbol: isExtension: false isInline: false isOverride: false - modality: FINAL + modality: ABSTRACT origin: SOURCE receiverParameter: null returnType: KtUsualClassType: diff --git a/analysis/analysis-api/testData/components/scopeProvider/declaredMemberScope/enumEntryInitializerWithOverriddenMember.txt b/analysis/analysis-api/testData/components/scopeProvider/declaredMemberScope/enumEntryInitializerWithOverriddenMember.txt index 57f58284100..082166e0e31 100644 --- a/analysis/analysis-api/testData/components/scopeProvider/declaredMemberScope/enumEntryInitializerWithOverriddenMember.txt +++ b/analysis/analysis-api/testData/components/scopeProvider/declaredMemberScope/enumEntryInitializerWithOverriddenMember.txt @@ -31,7 +31,7 @@ KtKotlinPropertySymbol: isExtension: false isInline: false isOverride: true - modality: FINAL + modality: OPEN origin: SOURCE receiverParameter: null returnType: KtUsualClassType: diff --git a/analysis/analysis-api/testData/components/scopeProvider/memberScope/enumClassWithAbstractMembers.txt b/analysis/analysis-api/testData/components/scopeProvider/memberScope/enumClassWithAbstractMembers.txt index 25b18cae8fb..1ff816c6fa7 100644 --- a/analysis/analysis-api/testData/components/scopeProvider/memberScope/enumClassWithAbstractMembers.txt +++ b/analysis/analysis-api/testData/components/scopeProvider/memberScope/enumClassWithAbstractMembers.txt @@ -31,7 +31,7 @@ KtKotlinPropertySymbol: isExtension: false isInline: false isOverride: false - modality: FINAL + modality: ABSTRACT origin: SOURCE receiverParameter: null returnType: KtUsualClassType: diff --git a/analysis/analysis-api/testData/components/scopeProvider/memberScope/enumEntryInitializerWithOverriddenMember.txt b/analysis/analysis-api/testData/components/scopeProvider/memberScope/enumEntryInitializerWithOverriddenMember.txt index 09643cb2951..e1eb6ec3634 100644 --- a/analysis/analysis-api/testData/components/scopeProvider/memberScope/enumEntryInitializerWithOverriddenMember.txt +++ b/analysis/analysis-api/testData/components/scopeProvider/memberScope/enumEntryInitializerWithOverriddenMember.txt @@ -31,7 +31,7 @@ KtKotlinPropertySymbol: isExtension: false isInline: false isOverride: true - modality: FINAL + modality: OPEN origin: SOURCE receiverParameter: null returnType: KtUsualClassType: diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryOverride.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryOverride.txt index 431213ceba9..acd2e1dcb5a 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryOverride.txt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryOverride.txt @@ -166,7 +166,7 @@ KtKotlinPropertySymbol: isExtension: false isInline: false isOverride: true - modality: FINAL + modality: OPEN origin: SOURCE receiverParameter: null returnType: KtUsualClassType: @@ -497,7 +497,7 @@ KtKotlinPropertySymbol: isExtension: false isInline: false isOverride: false - modality: FINAL + modality: OPEN origin: SOURCE receiverParameter: null returnType: KtUsualClassType: diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/enumValueMember.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/enumValueMember.txt index 79f079e7c39..a1a267cf44b 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/enumValueMember.txt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/enumValueMember.txt @@ -170,7 +170,7 @@ KtKotlinPropertySymbol: isExtension: false isInline: false isOverride: true - modality: FINAL + modality: OPEN origin: SOURCE receiverParameter: null returnType: KtUsualClassType: @@ -278,7 +278,7 @@ KtKotlinPropertySymbol: isExtension: false isInline: false isOverride: false - modality: FINAL + modality: ABSTRACT origin: SOURCE receiverParameter: null returnType: KtUsualClassType: diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolver.kt index a021a425218..4fb8337a289 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolver.kt @@ -10,10 +10,7 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl -import org.jetbrains.kotlin.fir.declarations.utils.effectiveVisibility -import org.jetbrains.kotlin.fir.declarations.utils.isExpect -import org.jetbrains.kotlin.fir.declarations.utils.isOverride -import org.jetbrains.kotlin.fir.declarations.utils.visibility +import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.extensions.FirStatusTransformerExtension import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.extensions.statusTransformerExtensions @@ -271,7 +268,7 @@ class FirStatusResolver( } else { it } - } ?: resolveModality(declaration, containingClass) + } ?: resolveModality(declaration, containingProperty, containingClass) if (overriddenStatuses.isNotEmpty()) { for (modifier in MODIFIERS_FROM_OVERRIDDEN) { status[modifier] = status[modifier] || overriddenStatuses.fold(false) { acc, overriddenStatus -> @@ -437,11 +434,13 @@ class FirStatusResolver( private fun resolveModality( declaration: FirDeclaration, + containingProperty: FirProperty?, containingClass: FirClass?, ): Modality { return when (declaration) { is FirRegularClass -> if (declaration.classKind == ClassKind.INTERFACE) Modality.ABSTRACT else Modality.FINAL is FirCallableDeclaration -> { + val containingPropertyModality = containingProperty?.modality when { containingClass == null -> Modality.FINAL containingClass.classKind == ClassKind.INTERFACE -> { @@ -451,6 +450,7 @@ class FirStatusResolver( else -> Modality.OPEN } } + declaration is FirPropertyAccessor && containingPropertyModality != null -> containingPropertyModality declaration.isOverride -> Modality.OPEN else -> Modality.FINAL } diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeSetterVisibilityInOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeSetterVisibilityInOverride.fir.kt index 964d3653e30..d3435ebfd45 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeSetterVisibilityInOverride.fir.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeSetterVisibilityInOverride.fir.kt @@ -12,6 +12,6 @@ open class Base { // FILE: jvm.kt actual open class Foo : Base() { - override var foo: String = "" + override var foo: String = "" public set } diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeSetterVisibilityInOverride.ll.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeSetterVisibilityInOverride.ll.kt index 0456ae6b5f0..f0adf91606f 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeSetterVisibilityInOverride.ll.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeSetterVisibilityInOverride.ll.kt @@ -12,6 +12,6 @@ expect open class Foo : Base // FILE: jvm.kt actual open class Foo : Base() { - override var foo: String = "" + override var foo: String = "" public set } diff --git a/compiler/testData/ir/irText/stubs/genericClassInDifferentModule.fir.ir.txt b/compiler/testData/ir/irText/stubs/genericClassInDifferentModule.fir.ir.txt index c53815afd8f..6f07e8129b9 100644 --- a/compiler/testData/ir/irText/stubs/genericClassInDifferentModule.fir.ir.txt +++ b/compiler/testData/ir/irText/stubs/genericClassInDifferentModule.fir.ir.txt @@ -87,7 +87,7 @@ FILE fqName: fileName:/genericClassInDifferentModule_m2.kt FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:OPEN <> ($this:.Derived1.Derived1>) returnType:T of .Derived1 correspondingProperty: PROPERTY name:bar visibility:public modality:OPEN [var] overridden: - public final fun (): T of .Base declared in .Base + public abstract fun (): T of .Base declared in .Base $this: VALUE_PARAMETER name: type:.Derived1.Derived1> BLOCK_BODY RETURN type=kotlin.Nothing from='public open fun (): T of .Derived1 declared in .Derived1' @@ -96,7 +96,7 @@ FILE fqName: fileName:/genericClassInDifferentModule_m2.kt FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:OPEN <> ($this:.Derived1.Derived1>, :T of .Derived1) returnType:kotlin.Unit correspondingProperty: PROPERTY name:bar visibility:public modality:OPEN [var] overridden: - public final fun (value: T of .Base): kotlin.Unit declared in .Base + public abstract fun (value: T of .Base): kotlin.Unit declared in .Base $this: VALUE_PARAMETER name: type:.Derived1.Derived1> VALUE_PARAMETER name: index:0 type:T of .Derived1 BLOCK_BODY @@ -109,7 +109,7 @@ FILE fqName: fileName:/genericClassInDifferentModule_m2.kt FUN name: visibility:public modality:OPEN ($this:.Derived1.Derived1>, $receiver:Z of .Derived1.) returnType:T of .Derived1 correspondingProperty: PROPERTY name:exn visibility:public modality:OPEN [var] overridden: - public final fun (): T of .Base declared in .Base + public abstract fun (): T of .Base declared in .Base TYPE_PARAMETER name:Z index:0 variance: superTypes:[kotlin.Any?] reified:false $this: VALUE_PARAMETER name: type:.Derived1.Derived1> $receiver: VALUE_PARAMETER name: type:Z of .Derived1. @@ -120,7 +120,7 @@ FILE fqName: fileName:/genericClassInDifferentModule_m2.kt FUN name: visibility:public modality:OPEN ($this:.Derived1.Derived1>, $receiver:Z of .Derived1., value:T of .Derived1) returnType:kotlin.Unit correspondingProperty: PROPERTY name:exn visibility:public modality:OPEN [var] overridden: - public final fun (value: T of .Base): kotlin.Unit declared in .Base + public abstract fun (value: T of .Base): kotlin.Unit declared in .Base TYPE_PARAMETER name:Z index:0 variance: superTypes:[kotlin.Any?] reified:false $this: VALUE_PARAMETER name: type:.Derived1.Derived1> $receiver: VALUE_PARAMETER name: type:Z of .Derived1.