From ac729e28da0dff6db143007cbe4427d4cf467e62 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 26 Jan 2024 11:33:57 +0100 Subject: [PATCH] K2/Java: fix processing of built-in with value parameters to be erased in Java In this commit we started to create and process a hidden copy for a built-in functions, which value parameters are erased in Java, in case we have an accidental Java override which value parameters are not erased. In this situation attempt to override such a Java override in Kotlin again will lead to inaccessible functions (see changes in containsAndOverload.fir.kt) #KT-64846 In Progress --- .../scopes/JavaClassUseSiteMemberScope.kt | 26 ++++++++++++++++--- .../containsAndOverload.fir.kt | 8 +++--- .../containsAndOverload.fir.overrides.txt | 5 ++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt index 66029ad14c9..e6e44b255b8 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt @@ -493,13 +493,13 @@ class JavaClassUseSiteMemberScope( return false } - val hasAccidentalOverrideWithDeclaredFunction = explicitlyDeclaredFunctionsWithNaturalName.any { + val accidentalOverrideWithDeclaredFunction = explicitlyDeclaredFunctionsWithNaturalName.find { overrideChecker.isOverriddenFunction( renamedDeclaredFunction, it ) } - if (!hasAccidentalOverrideWithDeclaredFunction) { + if (accidentalOverrideWithDeclaredFunction == null) { destination += renamedDeclaredFunction directOverriddenFunctions[renamedDeclaredFunction] = listOf(resultOfIntersectionWithNaturalName) for (overriddenMember in overriddenMembers) { @@ -508,9 +508,29 @@ class JavaClassUseSiteMemberScope( if (explicitlyDeclaredFunctionWithNaturalName != null) { destination += explicitlyDeclaredFunctionWithNaturalName } + return true + } else { + val newSymbol = FirNamedFunctionSymbol(accidentalOverrideWithDeclaredFunction.callableId) + val original = accidentalOverrideWithDeclaredFunction.fir + val hiddenFunction = buildSimpleFunctionCopy(original) { + name = naturalName + symbol = newSymbol + dispatchReceiverType = klass.defaultType() + }.apply { + initialSignatureAttr = original + isHiddenToOvercomeSignatureClash = true + } + destination += hiddenFunction.symbol + directOverriddenFunctions[hiddenFunction.symbol] = listOf(resultOfIntersectionWithNaturalName) + for (overriddenMember in overriddenMembers) { + overrideByBase[overriddenMember.member] = hiddenFunction.symbol + } + if (explicitlyDeclaredFunctionWithNaturalName != null) { + destination += explicitlyDeclaredFunctionWithNaturalName + } + return true } - return false } private fun FirNamedFunctionSymbol.hasSameJvmDescriptor( diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAndOverload.fir.kt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAndOverload.fir.kt index d650cc08a82..85174b43c7a 100644 --- a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAndOverload.fir.kt +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAndOverload.fir.kt @@ -18,8 +18,8 @@ fun foo(a: A, ka: KA) { "" in a 1 in a - ka.contains("") - ka.contains(1) - "" in ka - 1 in ka + ka.contains("") + ka.contains(1) + "" in ka + 1 in ka } diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAndOverload.fir.overrides.txt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAndOverload.fir.overrides.txt index 846c97e9516..83326a774a2 100644 --- a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAndOverload.fir.overrides.txt +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAndOverload.fir.overrides.txt @@ -5,3 +5,8 @@ KA: [SubstitutionOverride(DeclarationSite)]: public abstract operator fun contains(element: R|E|): R|kotlin/Boolean| from Use site scope of kotlin/collections/MutableCollection [id: 3] [SubstitutionOverride(DeclarationSite)]: public abstract operator fun contains(element: R|E|): R|kotlin/Boolean| from Substitution scope for [Use site scope of kotlin/collections/Collection] for type kotlin/collections/MutableCollection [id: 3] [Library]: public abstract operator fun contains(element: R|E|): R|kotlin/Boolean| from Use site scope of kotlin/collections/Collection [id: 4] + [Enhancement]: /* hidden due to clash */ public open operator fun contains(x: R|kotlin/String!|): R|kotlin/Boolean| from Java enhancement scope for /A [id: 5] + [SubstitutionOverride(DeclarationSite)]: public abstract operator fun contains(element: R|kotlin/String!|): R|kotlin/Boolean| from Substitution scope for [Use site scope of kotlin/collections/MutableCollection] for type A [id: 2] + [SubstitutionOverride(DeclarationSite)]: public abstract operator fun contains(element: R|E|): R|kotlin/Boolean| from Use site scope of kotlin/collections/MutableCollection [id: 3] + [SubstitutionOverride(DeclarationSite)]: public abstract operator fun contains(element: R|E|): R|kotlin/Boolean| from Substitution scope for [Use site scope of kotlin/collections/Collection] for type kotlin/collections/MutableCollection [id: 3] + [Library]: public abstract operator fun contains(element: R|E|): R|kotlin/Boolean| from Use site scope of kotlin/collections/Collection [id: 4]