From ff000173fc2ee9356f7e41e492fc00911fe9f99f Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 15 Mar 2021 18:18:54 +0300 Subject: [PATCH] ~~~ --- .../FirNotImplementedOverrideChecker.kt | 10 +- .../fir/declarations/FakeOverrideUtils.kt | 97 +++++++++++-------- .../fir/declarations/FirDeclarationUtil.kt | 5 - .../tests/platformTypes/rawOverrides.fir.kt | 2 +- .../platformTypes/rawSamOverrides.fir.kt | 2 +- ...ertypeDifferentParameterNullability.fir.kt | 8 +- .../kSuspendFunctionAsSupertype.fir.kt | 2 +- .../abstract-classes/p-2/neg/1.7.fir.kt | 4 +- 8 files changed, 72 insertions(+), 58 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirNotImplementedOverrideChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirNotImplementedOverrideChecker.kt index 99110432b4a76..0002f3f27432e 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirNotImplementedOverrideChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirNotImplementedOverrideChecker.kt @@ -41,21 +41,23 @@ object FirNotImplementedOverrideChecker : FirClassChecker() { if (source.kind is FirFakeSourceElementKind) return val contributedMembers = collectCallableMembers(declaration, context) - val baseSymbolsForFakeOverrides = declaration.calcBaseSymbolsForFakeOverrides( + val trivialFakeOverrideStubs = declaration.computeFakeOverrideStubs( contributedMembers, context.session, context.sessionHolder.scopeSession ).filter { - val fir = it.fir + if (it !is FirFakeOverrideStub.Trivial) return@filter false + val fir = it.baseSymbol.fir fir is FirMemberDeclaration && fir.isAbstract && // TODO: FIR MPP support (fir.getContainingClass(context) as? FirRegularClass)?.isExpect == false } - if (baseSymbolsForFakeOverrides.isEmpty()) return + if (trivialFakeOverrideStubs.isEmpty()) return // TODO: differentiate type-substituted declarations. Otherwise, they will be reported as MANY_IMPL_MEMBER_NOT_IMPLEMENTED val sigToDeclarations = mutableMapOf>>() - for (baseSymbolForFakeOverride in baseSymbolsForFakeOverrides) { + for (trivialFakeOverrideStub in trivialFakeOverrideStubs) { + val baseSymbolForFakeOverride = trivialFakeOverrideStub.baseSymbol val sig = when (baseSymbolForFakeOverride) { is FirNamedFunctionSymbol -> SignaturePresenter.represent(baseSymbolForFakeOverride.fir) is FirPropertySymbol -> SignaturePresenter.represent(baseSymbolForFakeOverride.fir) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/declarations/FakeOverrideUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/declarations/FakeOverrideUtils.kt index 5900c787c86a2..4e9c28723fb37 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/declarations/FakeOverrideUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/declarations/FakeOverrideUtils.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.fir.declarations -import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.resolve.ScopeSession @@ -15,52 +14,57 @@ import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenProperties import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol -fun FirClass<*>.calcBaseSymbolsForFakeOverrides( - contributedDeclarations: Collection, +sealed class FirFakeOverrideStub(val baseSymbols: List>) { + class FromScope( + val symbol: FirCallableSymbol<*>, + baseSymbols: List> + ) : FirFakeOverrideStub(baseSymbols) + + class Trivial(baseSymbol: FirCallableSymbol<*>) : FirFakeOverrideStub(listOf(baseSymbol)) + + val baseSymbol get() = baseSymbols.single() +} + +private object FakeOverrideStubKey : FirDeclarationDataKey() + +var FirClass<*>.fakeOverrideStubs: List? + by FirDeclarationDataRegistry.data(FakeOverrideStubKey) + +fun FirClass<*>.computeFakeOverrideStubs( + realDeclarations: Collection, session: FirSession, scopeSession: ScopeSession, -): Collection> { - baseSymbolsForFakeOverrides?.let { return it } - val result = mutableListOf>() +): List { + fakeOverrideStubs?.let { return it } + val result = mutableListOf() val classScope = unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false) - fun checkFunctionSymbolAndAddToResult(originalSymbol: FirCallableSymbol<*>) { - this.computeBaseDeclarations( - originalSymbol, - contributedDeclarations, - result, - classScope, - FirTypeScope::getDirectOverriddenFunctions - ) - } - - fun checkPropertySymbolAndAddToResult(originalSymbol: FirCallableSymbol<*>) { - this.computeBaseDeclarations( - originalSymbol, - contributedDeclarations, - result, - classScope, - FirTypeScope::getDirectOverriddenProperties - ) - } - - val contributedDeclarationNames = contributedDeclarations.mapNotNullTo(mutableSetOf()) l@{ + val classLookupTag = symbol.toLookupTag() + val realDeclarationNames = realDeclarations.mapNotNullTo(mutableSetOf()) l@{ val callableDeclaration = (it as? FirCallableMemberDeclaration<*>) ?: return@l null - // TODO: for multi-inheritance, we may need much stronger conditions like something in [FakeOverrideGenerator] - // For now, collect non-abstract members only - if (callableDeclaration.status.modality == Modality.ABSTRACT) null + // We may need to create a new fake override; compute base symbols; or deal with name conflicts. + if (callableDeclaration.symbol.shouldHaveComputedBaseSymbolsForClass(classLookupTag) || + callableDeclaration.allowsToHaveFakeOverrideIn(this) || + callableDeclaration.visibility == Visibilities.Private + ) null // Otherwise, bail out early based on the name of the contributed member declaration else callableDeclaration.symbol.callableId.callableName } - val superTypesCallableNames = classScope.getCallableNames().filter { it !in contributedDeclarationNames } + val superTypesCallableNames = classScope.getCallableNames().filter { it !in realDeclarationNames } for (name in superTypesCallableNames) { classScope.processFunctionsByName(name) { functionSymbol -> // TODO: MANY_* as well as some conflict diagnostics //if (functionSymbol is FirIntersectionOverrideFunctionSymbol) // functionSymbol.intersections.forEach(::checkFunctionSymbolAndAddToResult) //else - checkFunctionSymbolAndAddToResult(functionSymbol) + computeFakeOverrideStubsForSymbol( + functionSymbol, + realDeclarations, + result, + classScope, + FirTypeScope::getDirectOverriddenFunctions + ) } classScope.processPropertiesByName(name) { propertySymbol -> @@ -68,22 +72,31 @@ fun FirClass<*>.calcBaseSymbolsForFakeOverrides( //if (propertySymbol is FirIntersectionOverridePropertySymbol) // propertySymbol.intersections.forEach(::checkPropertySymbolAndAddToResult) //else - checkPropertySymbolAndAddToResult(propertySymbol) + computeFakeOverrideStubsForSymbol( + propertySymbol, + realDeclarations, + result, + classScope, + FirTypeScope::getDirectOverriddenProperties + ) } } - baseSymbolsForFakeOverrides = result + fakeOverrideStubs = result return result } -private inline fun , reified S : FirCallableSymbol> FirClass<*>.computeBaseDeclarations( +private inline fun < + reified D : FirCallableMemberDeclaration, + reified S : FirCallableSymbol + > FirClass<*>.computeFakeOverrideStubsForSymbol( originalSymbol: FirCallableSymbol<*>, - contributedDeclarations: Collection, - result: MutableList>, + realDeclarations: Collection, + result: MutableList, scope: FirTypeScope, computeDirectOverridden: FirTypeScope.(S) -> List, ) { - if (originalSymbol !is S || originalSymbol.fir in contributedDeclarations) return + if (originalSymbol !is S || originalSymbol.fir in realDeclarations) return val classLookupTag = symbol.toLookupTag() val originalDeclaration = originalSymbol.fir if (originalSymbol.dispatchReceiverClassOrNull() == classLookupTag && !originalDeclaration.origin.fromSupertypes) return @@ -92,12 +105,16 @@ private inline fun , reified S : Fir originalSymbol.shouldHaveComputedBaseSymbolsForClass(classLookupTag) -> { // Substitution or intersection case. // The current one is a FIR declaration for that fake override, and we can compute base symbols from it. - computeBaseSymbols(originalSymbol, computeDirectOverridden, scope, classLookupTag) + result.add( + FirFakeOverrideStub.FromScope( + originalSymbol, computeBaseSymbols(originalSymbol, computeDirectOverridden, scope, classLookupTag) + ) + ) } originalDeclaration.allowsToHaveFakeOverrideIn(firClass = this) -> { // Trivial fake override case. // FIR2IR will create a fake override in BE IR directly, and the current one _is_ the base declaration. - result.add(originalSymbol) + result.add(FirFakeOverrideStub.Trivial(originalSymbol)) } } } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationUtil.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationUtil.kt index 90b7f3f501971..924a1730f042d 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationUtil.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationUtil.kt @@ -187,11 +187,6 @@ private object IsReferredViaField : FirDeclarationDataKey() var FirProperty.isFromVararg: Boolean? by FirDeclarationDataRegistry.data(IsFromVarargKey) var FirProperty.isReferredViaField: Boolean? by FirDeclarationDataRegistry.data(IsReferredViaField) -private object BaseSymbolsForFakeOverrides : FirDeclarationDataKey() - -var FirClass<*>.baseSymbolsForFakeOverrides: Collection>? - by FirDeclarationDataRegistry.data(BaseSymbolsForFakeOverrides) - // See [BindingContext.BACKING_FIELD_REQUIRED] val FirProperty.hasBackingField: Boolean get() { diff --git a/compiler/testData/diagnostics/tests/platformTypes/rawOverrides.fir.kt b/compiler/testData/diagnostics/tests/platformTypes/rawOverrides.fir.kt index 6dab60f9d3dc7..2923b6e054953 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/rawOverrides.fir.kt +++ b/compiler/testData/diagnostics/tests/platformTypes/rawOverrides.fir.kt @@ -33,7 +33,7 @@ class E : D(), B { override fun bar(x: CharSequence?, y: List<*>?): String = "" } -class E2 : B { +class E2 : B { override fun foo(x: Any, y: List): String = "" } diff --git a/compiler/testData/diagnostics/tests/platformTypes/rawSamOverrides.fir.kt b/compiler/testData/diagnostics/tests/platformTypes/rawSamOverrides.fir.kt index ce1dd6cabcd38..bfd6557874e63 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/rawSamOverrides.fir.kt +++ b/compiler/testData/diagnostics/tests/platformTypes/rawSamOverrides.fir.kt @@ -36,6 +36,6 @@ class E1 : C.D(), B { override fun foo(x: Any, y: Fun) {} } -class E2 : B { +class E2 : B { override fun foo(x: Any, y: Fun) {} } diff --git a/compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/supertypeDifferentParameterNullability.fir.kt b/compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/supertypeDifferentParameterNullability.fir.kt index e5a29f8cb1dc8..229f827b62106 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/supertypeDifferentParameterNullability.fir.kt +++ b/compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/supertypeDifferentParameterNullability.fir.kt @@ -14,20 +14,20 @@ public interface B { // FILE: C.kt -class C1 : A, B { +class C1 : A, B { override fun foo(x: String) {} } -class C2 : A, B { +class C2 : A, B { override fun foo(x: String?) {} } interface I : A, B -class C3 : I { +class C3 : I { override fun foo(x: String) {} } -class C4 : I { +class C4 : I { override fun foo(x: String?) {} } diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/kSuspendFunctionAsSupertype.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/kSuspendFunctionAsSupertype.fir.kt index ad940515d8c12..ec1c040f115a8 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/kSuspendFunctionAsSupertype.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/kSuspendFunctionAsSupertype.fir.kt @@ -2,4 +2,4 @@ import kotlin.reflect.* -class A: KSuspendFunction0 {} \ No newline at end of file +class A: KSuspendFunction0 {} diff --git a/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.7.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.7.fir.kt index 499fc322cdac7..96fdb6571c46d 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.7.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.7.fir.kt @@ -59,7 +59,7 @@ fun case2() { // TESTCASE NUMBER: 3 -class Case3 : BaseKotlin() {} +class Case3 : BaseKotlin() {} fun case3() { val v = Case3() @@ -73,7 +73,7 @@ fun case3() { */ abstract class AbstractClassCase4 : BaseKotlin() {} -class Case4 : AbstractClassCase4() {} +class Case4 : AbstractClassCase4() {} fun case4() { val v = Case4()