diff --git a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt index 5fe96d714df..98ec272b244 100644 --- a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt +++ b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt @@ -296,13 +296,22 @@ class FirElementSerializer private constructor( processScope(memberScope) l@{ val declaration = it.fir as T - if (declaration.isSubstitutionOrIntersectionOverride) return@l - - // non-intersection or substitution fake override - if (!(declaration.isStatic || declaration is FirConstructor)) { - if (declaration.dispatchReceiverClassLookupTagOrNull() != this@collectDeclarations.symbol.toLookupTag()) { + val dispatchReceiverLookupTag = declaration.dispatchReceiverClassLookupTagOrNull() + // Special case for data/value class equals/hashCode/toString, see KT-57510 + val isOverrideOfAnyFunctionInDataOrValueClass = this@collectDeclarations is FirRegularClass && + (this@collectDeclarations.isData || this@collectDeclarations.isInline) && + dispatchReceiverLookupTag?.classId == StandardClassIds.Any && !declaration.isFinal + if (declaration.isSubstitutionOrIntersectionOverride) { + if (!isOverrideOfAnyFunctionInDataOrValueClass) { return@l } + } else if (!(declaration.isStatic || declaration is FirConstructor)) { + // non-intersection or substitution fake override + if (dispatchReceiverLookupTag != this@collectDeclarations.symbol.toLookupTag()) { + if (!isOverrideOfAnyFunctionInDataOrValueClass) { + return@l + } + } } add(declaration) diff --git a/compiler/testData/codegen/box/reflection/classes/declaredMembers.kt b/compiler/testData/codegen/box/reflection/classes/declaredMembers.kt index 85e6ba8d159..8605f3e7081 100644 --- a/compiler/testData/codegen/box/reflection/classes/declaredMembers.kt +++ b/compiler/testData/codegen/box/reflection/classes/declaredMembers.kt @@ -42,6 +42,14 @@ inline fun test(vararg names: String) { assertEquals(names.toSet(), T::class.declaredMembers.map { it.name }.toSet()) } +data class D(val x: Int) + +open class O(val y: T) +data class DO(val z: Int) : O(2 * z) + +@JvmInline +value class V(val b: Boolean) + fun box(): String { class Local : L() { fun publicLocalFun() {} @@ -55,6 +63,9 @@ fun box(): String { test("publicKFun", "privateKFun", "publicKProp", "privateKProp") test("publicLFun", "privateLFun", "publicLProp", "privateLProp") test("publicLocalFun", "privateLocalFun", "publicLocalProp", "privateLocalProp") + test("x", "component1", "copy", "equals", "hashCode", "toString") + test("z", "component1", "copy", "equals", "hashCode", "toString") + test("b", "equals", "hashCode", "toString") return "OK" }