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 ba6b3f6bfd6..bf257cd23b5 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 @@ -63,6 +63,8 @@ class JavaClassUseSiteMemberScope( private val canUseSpecialGetters: Boolean by lazy { !klass.hasKotlinSuper(session) } + private val javaOverrideChecker: JavaOverrideChecker get() = overrideChecker as JavaOverrideChecker + private fun generateSyntheticPropertySymbol( getterSymbol: FirNamedFunctionSymbol, setterSymbol: FirNamedFunctionSymbol?, @@ -343,8 +345,9 @@ class JavaClassUseSiteMemberScope( destination: MutableCollection ) { val resultsOfIntersectionToSaveInCache = mutableListOf>() - val list = supertypeScopeContext.convertGroupedCallablesToIntersectionResults(functionsFromSupertypesWithRequestedName) - for (resultOfIntersectionWithNaturalName in list) { + val intersectionResults = + supertypeScopeContext.convertGroupedCallablesToIntersectionResults(functionsFromSupertypesWithRequestedName) + for (resultOfIntersectionWithNaturalName in intersectionResults) { val someSymbolWithNaturalNameFromSuperType = resultOfIntersectionWithNaturalName.extractSomeSymbolFromSuperType() val explicitlyDeclaredFunctionWithNaturalName = explicitlyDeclaredFunctionsWithNaturalName.firstOrNull { overrideChecker.isOverriddenFunction(it, someSymbolWithNaturalNameFromSuperType) @@ -415,7 +418,8 @@ class JavaClassUseSiteMemberScope( ?.symbol as? FirNamedFunctionSymbol ?: unwrappedSubstitutionOverride.symbol val originalDeclaredFunction = declaredMemberScope.getFunctions(naturalName).firstOrNull { - it.hasSameJvmDescriptor(functionFromSupertypeWithErasedParameterType) && it.hasErasedParameters() + it.hasSameJvmDescriptor(functionFromSupertypeWithErasedParameterType) && it.hasErasedParameters() && + javaOverrideChecker.doesReturnTypesHaveSameKind(functionFromSupertypeWithErasedParameterType.fir, it.fir) } ?: return false val renamedDeclaredFunction = buildJavaMethodCopy(originalDeclaredFunction.fir as FirJavaMethod) { name = naturalName diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaOverrideChecker.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaOverrideChecker.kt index 075ba4de17a..44ab3a88eb3 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaOverrideChecker.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaOverrideChecker.kt @@ -90,7 +90,7 @@ class JavaOverrideChecker internal constructor( // In most cases checking erasure of value parameters should be enough, but in some cases there might be semi-valid Java hierarchies // with same value parameters, but different return type kinds, so it's worth distinguishing them as different non-overridable members - private fun doesReturnTypesHaveSameKind( + fun doesReturnTypesHaveSameKind( candidate: FirSimpleFunction, base: FirSimpleFunction, ): Boolean { diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/firIncorrectRemoveSignature/A.java b/compiler/testData/compileKotlinAgainstCustomBinaries/firIncorrectRemoveSignature/A.java new file mode 100644 index 00000000000..aca4d965ccc --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/firIncorrectRemoveSignature/A.java @@ -0,0 +1,4 @@ +package test; +public interface A extends java.util.Map { + String remove(Object x, Object y); +} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/firIncorrectRemoveSignature/B.java b/compiler/testData/compileKotlinAgainstCustomBinaries/firIncorrectRemoveSignature/B.java new file mode 100644 index 00000000000..36c804105fa --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/firIncorrectRemoveSignature/B.java @@ -0,0 +1,4 @@ +package test; +public abstract class B implements java.util.Map, A { + public String remove(Object x, Object y) { return x; } +} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/firIncorrectRemoveSignature/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/firIncorrectRemoveSignature/output.txt new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/firIncorrectRemoveSignature/output.txt @@ -0,0 +1 @@ +OK diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/firIncorrectRemoveSignature/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/firIncorrectRemoveSignature/source.kt new file mode 100644 index 00000000000..68581299097 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/firIncorrectRemoveSignature/source.kt @@ -0,0 +1,3 @@ +package test + +abstract class C : B() diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt index b1538efd9a8..b5613575d60 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt @@ -638,6 +638,15 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration ) } + fun testFirIncorrectRemoveSignature() { + compileKotlin( + "source.kt", tmpdir, + listOf(), + additionalOptions = listOf("-Xuse-k2"), + additionalSources = listOf("A.java", "B.java"), + ) + } + fun testOldJvmAgainstJvmIr() { val library = compileLibrary("library", additionalOptions = listOf("-Xuse-ir")) compileKotlin("source.kt", tmpdir, listOf(library))