From 471134d31ee7212d3c5fccea867f3f4007afda76 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Mon, 1 Apr 2019 15:34:02 +0300 Subject: [PATCH] [Invariant Fix] Fix callable equivalence definition in case of refined scopes Before types refinement has been introduced it was reasonable to assume that whenever we have two callables in the same declaration they are actually different But it become false once types refinement were introduced and the same declarations may appear as different descriptors' instances when viewing from different modules The change does look very fragile because in many cases source element is NO_SOURCE At the same time, declaring actually different members with the same signature is prohibited and may make sense only in case of source-based members --- .../resolve/DescriptorEquivalenceForOverrides.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorEquivalenceForOverrides.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorEquivalenceForOverrides.kt index adc9b2cded3..4c6ecc86ebe 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorEquivalenceForOverrides.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorEquivalenceForOverrides.kt @@ -57,6 +57,12 @@ object DescriptorEquivalenceForOverrides { return a.index == b.index // We ignore type parameter names } + private tailrec fun CallableDescriptor.singleSource(): SourceElement? { + if (this !is CallableMemberDescriptor || kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) return source + + return overriddenDescriptors.singleOrNull()?.singleSource() + } + fun areCallableDescriptorsEquivalent( a: CallableDescriptor, b: CallableDescriptor, @@ -64,7 +70,10 @@ object DescriptorEquivalenceForOverrides { ): Boolean { if (a == b) return true if (a.name != b.name) return false - if (a.containingDeclaration == b.containingDeclaration) return false + if (a.containingDeclaration == b.containingDeclaration) { + if (a.singleSource() != b.singleSource()) return false + if (a is MemberDescriptor && b is MemberDescriptor && a.isExpect != b.isExpect) return false + } // Distinct locals are not equivalent if (DescriptorUtils.isLocal(a) || DescriptorUtils.isLocal(b)) return false