From 668157eb4191f61dd02e3d281a005f1f31fd9f49 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 26 May 2023 09:04:31 +0200 Subject: [PATCH] FirClassAnySynthesizedMemberScope.kt: make it a declared member scope Related to KT-54844, KT-58926 --- ...cCompilerTestFirTestdataTestGenerated.java | 6 + ...osticCompilerFirTestDataTestGenerated.java | 6 + .../LazyBodyIsNotTouchedTestGenerated.java | 5 + .../resolve/scopes/delegatedDataClass.fir.txt | 42 +++++++ .../resolve/scopes/delegatedDataClass.kt | 25 ++++ .../scopes/delegatedDataClass.overrides.txt | 14 +++ .../FirLightTreeDiagnosticsTestGenerated.java | 6 + .../FirPsiDiagnosticTestGenerated.java | 6 + ...LightTreeBlackBoxCodegenTestGenerated.java | 6 + .../FirPsiBlackBoxCodegenTestGenerated.java | 6 + .../fir/scopes/FirKotlinScopeProvider.kt | 24 ++-- .../impl/FirClassAnySynthesizedMemberScope.kt | 116 +++++++++--------- .../box/fir/delegatedAndDataTogether.kt | 20 +++ .../IrBlackBoxCodegenTestGenerated.java | 6 + ...kBoxCodegenWithIrInlinerTestGenerated.java | 6 + 15 files changed, 222 insertions(+), 72 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/scopes/delegatedDataClass.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/scopes/delegatedDataClass.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/scopes/delegatedDataClass.overrides.txt create mode 100644 compiler/testData/codegen/box/fir/delegatedAndDataTogether.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFirTestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFirTestdataTestGenerated.java index 73600644f98..7eab0910551 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFirTestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFirTestdataTestGenerated.java @@ -4195,6 +4195,12 @@ public class DiagnosticCompilerTestFirTestdataTestGenerated extends AbstractDiag KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/scopes"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("delegatedDataClass.kt") + public void testDelegatedDataClass() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/scopes/delegatedDataClass.kt"); + } + @Test @TestMetadata("explicitOverrideOfTwoMembers.kt") public void testExplicitOverrideOfTwoMembers() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFirTestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFirTestDataTestGenerated.java index 503715de505..2a42e3f5267 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFirTestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFirTestDataTestGenerated.java @@ -4195,6 +4195,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFirTestDataTestGenerated KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/scopes"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("delegatedDataClass.kt") + public void testDelegatedDataClass() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/scopes/delegatedDataClass.kt"); + } + @Test @TestMetadata("explicitOverrideOfTwoMembers.kt") public void testExplicitOverrideOfTwoMembers() throws Exception { diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTestGenerated.java b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTestGenerated.java index ce357e34804..9482efb0c52 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTestGenerated.java +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTestGenerated.java @@ -3699,6 +3699,11 @@ public class LazyBodyIsNotTouchedTestGenerated extends AbstractLazyBodyIsNotTouc KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/scopes"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @TestMetadata("delegatedDataClass.kt") + public void testDelegatedDataClass() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/scopes/delegatedDataClass.kt"); + } + @TestMetadata("explicitOverrideOfTwoMembers.kt") public void testExplicitOverrideOfTwoMembers() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/scopes/explicitOverrideOfTwoMembers.kt"); diff --git a/compiler/fir/analysis-tests/testData/resolve/scopes/delegatedDataClass.fir.txt b/compiler/fir/analysis-tests/testData/resolve/scopes/delegatedDataClass.fir.txt new file mode 100644 index 00000000000..86080d15b4a --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/scopes/delegatedDataClass.fir.txt @@ -0,0 +1,42 @@ +FILE: delegatedDataClass.kt + public abstract interface AnyNeighbor : R|kotlin/Any| { + public abstract override operator fun equals(other: R|kotlin/Any?|): R|kotlin/Boolean| + + public abstract override fun hashCode(): R|kotlin/Int| + + public abstract override fun toString(): R|kotlin/String| + + } + public final class Impl : R|AnyNeighbor| { + public constructor(): R|Impl| { + super() + } + + public open override operator fun equals(other: R|kotlin/Any?|): R|kotlin/Boolean| { + ^equals Boolean(true) + } + + public open override fun hashCode(): R|kotlin/Int| { + ^hashCode Int(0) + } + + public open override fun toString(): R|kotlin/String| { + ^toString String() + } + + } + public final data class Data : R|AnyNeighbor| { + public constructor(i: R|Impl|): R|Data| { + super() + } + + private final field $$delegate_0: R|AnyNeighbor| = R|/i| + + public final val i: R|Impl| = R|/i| + public get(): R|Impl| + + public final operator fun component1(): R|Impl| + + public final fun copy(i: R|Impl| = this@R|/Data|.R|/Data.i|): R|Data| + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/scopes/delegatedDataClass.kt b/compiler/fir/analysis-tests/testData/resolve/scopes/delegatedDataClass.kt new file mode 100644 index 00000000000..39765959b36 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/scopes/delegatedDataClass.kt @@ -0,0 +1,25 @@ +// SCOPE_DUMP: Data:equals, Data:hashCode, Data:toString + +interface AnyNeighbor { + override fun equals(other: Any?): Boolean + + override fun hashCode(): Int + + override fun toString(): String +} + +class Impl : AnyNeighbor { + override fun equals(other: Any?): Boolean { + return true + } + + override fun hashCode(): Int { + return 0 + } + + override fun toString(): String { + return "" + } +} + +data class Data(val i: Impl) : AnyNeighbor by i diff --git a/compiler/fir/analysis-tests/testData/resolve/scopes/delegatedDataClass.overrides.txt b/compiler/fir/analysis-tests/testData/resolve/scopes/delegatedDataClass.overrides.txt new file mode 100644 index 00000000000..06a60b62823 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/scopes/delegatedDataClass.overrides.txt @@ -0,0 +1,14 @@ +Data: + [Delegated]: public open override operator fun equals(other: R|kotlin/Any?|): R|kotlin/Boolean| from Use site scope of /Data [id: 0] + [Source]: public abstract override operator fun equals(other: R|kotlin/Any?|): R|kotlin/Boolean| from Use site scope of /AnyNeighbor [id: 1] + [Library]: public open operator fun equals(other: R|kotlin/Any?|): R|kotlin/Boolean| from Use site scope of kotlin/Any [id: 2] + +Data: + [Delegated]: public open override fun hashCode(): R|kotlin/Int| from Use site scope of /Data [id: 0] + [Source]: public abstract override fun hashCode(): R|kotlin/Int| from Use site scope of /AnyNeighbor [id: 1] + [Library]: public open fun hashCode(): R|kotlin/Int| from Use site scope of kotlin/Any [id: 2] + +Data: + [Delegated]: public open override fun toString(): R|kotlin/String| from Use site scope of /Data [id: 0] + [Source]: public abstract override fun toString(): R|kotlin/String| from Use site scope of /AnyNeighbor [id: 1] + [Library]: public open fun toString(): R|kotlin/String| from Use site scope of kotlin/Any [id: 2] diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeDiagnosticsTestGenerated.java index db722706aba..12b8f64c735 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeDiagnosticsTestGenerated.java @@ -4195,6 +4195,12 @@ public class FirLightTreeDiagnosticsTestGenerated extends AbstractFirLightTreeDi KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/scopes"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("delegatedDataClass.kt") + public void testDelegatedDataClass() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/scopes/delegatedDataClass.kt"); + } + @Test @TestMetadata("explicitOverrideOfTwoMembers.kt") public void testExplicitOverrideOfTwoMembers() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiDiagnosticTestGenerated.java index a16d3577742..abd9585ad60 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiDiagnosticTestGenerated.java @@ -4195,6 +4195,12 @@ public class FirPsiDiagnosticTestGenerated extends AbstractFirPsiDiagnosticTest KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/scopes"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("delegatedDataClass.kt") + public void testDelegatedDataClass() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/scopes/delegatedDataClass.kt"); + } + @Test @TestMetadata("explicitOverrideOfTwoMembers.kt") public void testExplicitOverrideOfTwoMembers() throws Exception { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java index 856c3878a18..8aaa28adb75 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java @@ -18411,6 +18411,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr runTest("compiler/testData/codegen/box/fir/CustomThrowableMessage.kt"); } + @Test + @TestMetadata("delegatedAndDataTogether.kt") + public void testDelegatedAndDataTogether() throws Exception { + runTest("compiler/testData/codegen/box/fir/delegatedAndDataTogether.kt"); + } + @Test @TestMetadata("differentSinceKotlin.kt") public void testDifferentSinceKotlin() throws Exception { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java index dcb6031c3d3..e6e680cc8b9 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java @@ -18411,6 +18411,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo runTest("compiler/testData/codegen/box/fir/CustomThrowableMessage.kt"); } + @Test + @TestMetadata("delegatedAndDataTogether.kt") + public void testDelegatedAndDataTogether() throws Exception { + runTest("compiler/testData/codegen/box/fir/delegatedAndDataTogether.kt"); + } + @Test @TestMetadata("differentSinceKotlin.kt") public void testDifferentSinceKotlin() throws Exception { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirKotlinScopeProvider.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirKotlinScopeProvider.kt index 6288c773897..a2f73772df3 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirKotlinScopeProvider.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirKotlinScopeProvider.kt @@ -45,7 +45,7 @@ class FirKotlinScopeProvider( return scopeSession.getOrBuild(klass.symbol, USE_SITE) { val declaredScope = useSiteSession.declaredMemberScope(klass, memberRequiredPhase) - val decoratedDeclaredMemberScope = declaredMemberScopeDecorator( + val possiblyDelegatedDeclaredMemberScope = declaredMemberScopeDecorator( klass, declaredScope, useSiteSession, @@ -58,29 +58,25 @@ class FirKotlinScopeProvider( else FirDelegatedMemberScope(useSiteSession, scopeSession, klass, it, delegateFields) } + val declaredMemberScopeWithPossiblySynthesizedMembers = + if (klass is FirRegularClass && !klass.isExpect && (klass.isData || klass.isInline)) { + // See also KT-58926 (we apply delegation first, and data/value classes after it) + FirClassAnySynthesizedMemberScope(useSiteSession, possiblyDelegatedDeclaredMemberScope, klass, scopeSession) + } else { + possiblyDelegatedDeclaredMemberScope + } val scopes = lookupSuperTypes( klass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession, substituteTypes = true ).mapNotNull { useSiteSuperType -> useSiteSuperType.scopeForSupertype(useSiteSession, scopeSession, klass, memberRequiredPhase = memberRequiredPhase) } - val useSiteMemberScope = FirClassUseSiteMemberScope( + FirClassUseSiteMemberScope( klass, useSiteSession, scopes, - decoratedDeclaredMemberScope, + declaredMemberScopeWithPossiblySynthesizedMembers, ) - if (klass is FirRegularClass && !klass.isExpect && (klass.isData || klass.isInline)) { - val lookupTag = klass.symbol.toLookupTag() - scopeSession.getOrBuild(lookupTag, AnySynthesizedScopeKey(lookupTag)) { - FirClassAnySynthesizedMemberScope( - useSiteSession, useSiteMemberScope, lookupTag, - klass.moduleData, klass.defaultType(), klass.source - ) - } - } else { - useSiteMemberScope - } } } diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassAnySynthesizedMemberScope.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassAnySynthesizedMemberScope.kt index 1767867ac08..5433eacb97f 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassAnySynthesizedMemberScope.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassAnySynthesizedMemberScope.kt @@ -6,12 +6,10 @@ package org.jetbrains.kotlin.fir.scopes.impl import org.jetbrains.kotlin.KtFakeSourceElementKind -import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.descriptors.EffectiveVisibility import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fakeElement -import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSessionComponent import org.jetbrains.kotlin.fir.caches.FirCache @@ -19,19 +17,22 @@ import org.jetbrains.kotlin.fir.caches.FirCachesFactory import org.jetbrains.kotlin.fir.caches.createCache import org.jetbrains.kotlin.fir.caches.firCachesFactory import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin +import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.builder.FirSimpleFunctionBuilder import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl +import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.defaultType +import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor -import org.jetbrains.kotlin.fir.scopes.FirTypeScope -import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope +import org.jetbrains.kotlin.fir.scopes.scopeForSupertype import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase -import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.impl.FirImplicitBooleanTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitIntTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitNullableAnyTypeRef @@ -41,86 +42,85 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled +/** + * This declared scope wrapper is created for data/value classes and provides Any method stubs, if necessary + */ class FirClassAnySynthesizedMemberScope( session: FirSession, - private val useSiteMemberScope: FirClassUseSiteMemberScope, - private val lookupTag: ConeClassLikeLookupTag, - private val baseModuleData: FirModuleData, - private val dispatchReceiverType: ConeClassLikeType, - classSource: KtSourceElement?, -) : FirTypeScope() { + private val declaredMemberScope: FirContainingNamesAwareScope, + klass: FirRegularClass, + scopeSession: ScopeSession, +) : FirContainingNamesAwareScope() { + private val lookupTag = klass.symbol.toLookupTag() + + private val baseModuleData = klass.moduleData + + private val dispatchReceiverType = klass.defaultType() + private val synthesizedCache = session.synthesizedStorage.synthesizedCacheByScope.getValue(lookupTag, null) - private val synthesizedOverrides = mutableMapOf() + private val synthesizedSource = klass.source?.fakeElement(KtFakeSourceElementKind.DataClassGeneratedMembers) - private val synthesizedSource = classSource?.fakeElement(KtFakeSourceElementKind.DataClassGeneratedMembers) + private val superKlassScope = lookupSuperTypes( + klass, lookupInterfaces = false, deep = false, useSiteSession = session, substituteTypes = true + ).firstOrNull()?.scopeForSupertype(session, scopeSession, klass, memberRequiredPhase = FirResolvePhase.TYPES) override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) { - useSiteMemberScope.processClassifiersByNameWithSubstitution(name, processor) + declaredMemberScope.processClassifiersByNameWithSubstitution(name, processor) } override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) { - useSiteMemberScope.processDeclaredConstructors(processor) - } - - override fun processDirectOverriddenPropertiesWithBaseScope( - propertySymbol: FirPropertySymbol, - processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction - ): ProcessorAction { - return useSiteMemberScope.processDirectOverriddenPropertiesWithBaseScope(propertySymbol, processor) - } - - override fun processDirectOverriddenFunctionsWithBaseScope( - functionSymbol: FirNamedFunctionSymbol, - processor: (FirNamedFunctionSymbol, FirTypeScope) -> ProcessorAction, - ): ProcessorAction { - val overridden = synthesizedOverrides[functionSymbol] - ?: return useSiteMemberScope.processDirectOverriddenFunctionsWithBaseScope(functionSymbol, processor) - return processor(overridden, useSiteMemberScope) + declaredMemberScope.processDeclaredConstructors(processor) } override fun getCallableNames(): Set { - return useSiteMemberScope.getCallableNames() + return declaredMemberScope.getCallableNames() } override fun getClassifierNames(): Set { - return useSiteMemberScope.getClassifierNames() + return declaredMemberScope.getClassifierNames() } override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) { - useSiteMemberScope.processPropertiesByName(name, processor) + declaredMemberScope.processPropertiesByName(name, processor) } override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) { if (name !in ANY_MEMBER_NAMES) { - useSiteMemberScope.processFunctionsByName(name, processor) + declaredMemberScope.processFunctionsByName(name, processor) return } - useSiteMemberScope.processFunctionsByName(name) { fromUseSiteScope -> - if (fromUseSiteScope.rawStatus.modality == Modality.FINAL) { - processor(fromUseSiteScope) - } else { - val matchedSomeAnyMember = when (name) { - OperatorNameConventions.HASH_CODE, OperatorNameConventions.TO_STRING -> { - fromUseSiteScope.valueParameterSymbols.isEmpty() && !fromUseSiteScope.isExtension && - fromUseSiteScope.fir.contextReceivers.isEmpty() - } - else -> { - fromUseSiteScope.lazyResolveToPhase(FirResolvePhase.TYPES) - fromUseSiteScope.fir.isEquals() - } - } - val hasSameReceiver = - dispatchReceiverType.lookupTag == (fromUseSiteScope.dispatchReceiverType as? ConeClassLikeType)?.lookupTag - if (!matchedSomeAnyMember || hasSameReceiver) { - processor(fromUseSiteScope) - } else { - val synthesized = synthesizedCache.synthesizedFunctionAndOverrides.getValue(name, this) - synthesizedOverrides[synthesized] = fromUseSiteScope - processor(synthesized) + var synthesizedFunctionIsNeeded = true + declaredMemberScope.processFunctionsByName(name) process@{ fromDeclaredScope -> + if (fromDeclaredScope.matchesSomeAnyMember(name)) { + // TODO: should we handle fromDeclaredScope.origin == FirDeclarationOrigin.Delegated somehow? + // See also KT-58926 + synthesizedFunctionIsNeeded = false + } + processor(fromDeclaredScope) + } + if (!synthesizedFunctionIsNeeded) return + superKlassScope?.processFunctionsByName(name) { fromSuperType -> + if (synthesizedFunctionIsNeeded) { + if (fromSuperType.rawStatus.modality == Modality.FINAL && fromSuperType.matchesSomeAnyMember(name)) { + synthesizedFunctionIsNeeded = false } } } + if (!synthesizedFunctionIsNeeded) return + processor(synthesizedCache.synthesizedFunction.getValue(name, this)) + } + + private fun FirNamedFunctionSymbol.matchesSomeAnyMember(name: Name): Boolean { + return when (name) { + OperatorNameConventions.HASH_CODE, OperatorNameConventions.TO_STRING -> { + valueParameterSymbols.isEmpty() && !isExtension && fir.contextReceivers.isEmpty() + } + else -> { + lazyResolveToPhase(FirResolvePhase.TYPES) + fir.isEquals() + } + } } internal fun generateSyntheticFunctionByName(name: Name): FirNamedFunctionSymbol = @@ -191,7 +191,7 @@ class FirSynthesizedStorage(val session: FirSession) : FirSessionComponent { cachesFactory.createCache { _ -> SynthesizedCache(session.firCachesFactory) } class SynthesizedCache(cachesFactory: FirCachesFactory) { - val synthesizedFunctionAndOverrides: FirCache = + val synthesizedFunction: FirCache = cachesFactory.createCache { name, scope -> scope.generateSyntheticFunctionByName(name) } } } diff --git a/compiler/testData/codegen/box/fir/delegatedAndDataTogether.kt b/compiler/testData/codegen/box/fir/delegatedAndDataTogether.kt new file mode 100644 index 00000000000..d176e6a27e9 --- /dev/null +++ b/compiler/testData/codegen/box/fir/delegatedAndDataTogether.kt @@ -0,0 +1,20 @@ +// TARGET_BACKEND: JVM_IR +// ISSUE: KT-58926 + +fun box(): String { + val i1 = Impl() + val i2 = Impl() + val d1 = Data(i1, 1) + val d2 = Data(i2, 2) + return if (d1 != d2) "FAIL: should be equal" else "OK" +} + +interface AnyNeighbor { + override fun equals(other: Any?): Boolean +} + +class Impl : AnyNeighbor { + override fun equals(other: Any?): Boolean = true +} + +data class Data(val i: Impl, val j: Int) : AnyNeighbor by i diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 24b84b67583..a9ad811ff23 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -18411,6 +18411,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/fir/CustomThrowableMessage.kt"); } + @Test + @TestMetadata("delegatedAndDataTogether.kt") + public void testDelegatedAndDataTogether() throws Exception { + runTest("compiler/testData/codegen/box/fir/delegatedAndDataTogether.kt"); + } + @Test @TestMetadata("differentSinceKotlin.kt") public void testDifferentSinceKotlin() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java index 262abc66bf3..a827c537948 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java @@ -18411,6 +18411,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack runTest("compiler/testData/codegen/box/fir/CustomThrowableMessage.kt"); } + @Test + @TestMetadata("delegatedAndDataTogether.kt") + public void testDelegatedAndDataTogether() throws Exception { + runTest("compiler/testData/codegen/box/fir/delegatedAndDataTogether.kt"); + } + @Test @TestMetadata("differentSinceKotlin.kt") public void testDifferentSinceKotlin() throws Exception {