diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java index 9917a0b3755..5bcafd145ca 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java @@ -23387,6 +23387,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/override/clashesOnInheritance"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform"); } + @Test + @TestMetadata("conflictingInherited.kt") + public void testConflictingInherited() throws Exception { + runTest("compiler/testData/diagnostics/tests/override/clashesOnInheritance/conflictingInherited.kt"); + } + @Test @TestMetadata("covariantOverrides.kt") public void testCovariantOverrides() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java index 52d8786054f..08f407e4484 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java @@ -23387,6 +23387,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/override/clashesOnInheritance"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform"); } + @Test + @TestMetadata("conflictingInherited.kt") + public void testConflictingInherited() throws Exception { + runTest("compiler/testData/diagnostics/tests/override/clashesOnInheritance/conflictingInherited.kt"); + } + @Test @TestMetadata("covariantOverrides.kt") public void testCovariantOverrides() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index 8b8149855be..bcc3ba28f8f 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -23387,6 +23387,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/override/clashesOnInheritance"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform"); } + @Test + @TestMetadata("conflictingInherited.kt") + public void testConflictingInherited() throws Exception { + runTest("compiler/testData/diagnostics/tests/override/clashesOnInheritance/conflictingInherited.kt"); + } + @Test @TestMetadata("covariantOverrides.kt") public void testCovariantOverrides() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index d10bfa2405d..7657c5f5425 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -23393,6 +23393,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/override/clashesOnInheritance"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform"); } + @Test + @TestMetadata("conflictingInherited.kt") + public void testConflictingInherited() throws Exception { + runTest("compiler/testData/diagnostics/tests/override/clashesOnInheritance/conflictingInherited.kt"); + } + @Test @TestMetadata("covariantOverrides.kt") public void testCovariantOverrides() throws Exception { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImplementationMismatchChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImplementationMismatchChecker.kt index baa117739b3..4ceb3829949 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImplementationMismatchChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImplementationMismatchChecker.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration import org.jetbrains.kotlin.KtFakeSourceElementKind +import org.jetbrains.kotlin.KtRealSourceElementKind import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope @@ -13,6 +14,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.impl.deduplicating import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.containingClassLookupTag import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.utils.classId @@ -195,16 +197,14 @@ object FirImplementationMismatchChecker : FirClassChecker() { ) { val allFunctions = mutableListOf() scope.processFunctionsByName(name) { sym -> - val declaredInThisClass = sym.callableId.classId == containingClass.classId - when { - sym is FirIntersectionOverrideFunctionSymbol && declaredInThisClass -> - sym.intersections.mapNotNullTo(allFunctions) { it as? FirNamedFunctionSymbol } - !declaredInThisClass -> allFunctions.add(sym) + when (sym) { + is FirIntersectionOverrideFunctionSymbol -> sym.intersections.mapNotNullTo(allFunctions) { it as? FirNamedFunctionSymbol } + else -> allFunctions.add(sym) } } val sameArgumentGroups = allFunctions.groupBy { function -> - buildList { + buildList { addIfNotNull(function.resolvedReceiverTypeRef?.type) function.valueParameterSymbols.mapTo(this) { it.resolvedReturnTypeRef.coneType } } @@ -216,8 +216,30 @@ object FirImplementationMismatchChecker : FirClassChecker() { } } - clashes.forEach { - reporter.reportOn(containingClass.source, FirErrors.CONFLICTING_INHERITED_MEMBERS, containingClass.symbol, it.toList(), context) + for (clash in clashes) { + val (first, second) = clash + + val firstClassLookupTag = first.containingClassLookupTag() + val secondClassLookupTag = second.containingClassLookupTag() + + if (firstClassLookupTag == secondClassLookupTag) { + // Don't report if both declarations came from the same class because either CONFLICTING_OVERLOADS was reported in the + // original class or it's ok to keep compatibility with K1. See KT-55860. + continue + } + + val thisClassLookupTag = containingClass.symbol.toLookupTag() + + // If one of the declarations is from this class, report CONFLICTING_OVERLOADS, otherwise CONFLICTING_INHERITED_MEMBERS + if (firstClassLookupTag == thisClassLookupTag && first.source?.kind is KtRealSourceElementKind) { + reporter.reportOn(first.source, FirErrors.CONFLICTING_OVERLOADS, clash.toList(), context) + } else if (secondClassLookupTag == thisClassLookupTag && second.source?.kind is KtRealSourceElementKind) { + reporter.reportOn(second.source, FirErrors.CONFLICTING_OVERLOADS, clash.toList(), context) + } else { + reporter.reportOn( + containingClass.source, FirErrors.CONFLICTING_INHERITED_MEMBERS, containingClass.symbol, clash.toList(), context, + ) + } } } diff --git a/compiler/testData/diagnostics/tests/override/ConflictingFunctionSignatureFromSuperclass.fir.kt b/compiler/testData/diagnostics/tests/override/ConflictingFunctionSignatureFromSuperclass.fir.kt deleted file mode 100644 index a4e1448448d..00000000000 --- a/compiler/testData/diagnostics/tests/override/ConflictingFunctionSignatureFromSuperclass.fir.kt +++ /dev/null @@ -1,7 +0,0 @@ -open class Aaa() { - fun foo() = 1 -} - -open class Bbb() : Aaa() { - fun foo() = 2 -} diff --git a/compiler/testData/diagnostics/tests/override/ConflictingFunctionSignatureFromSuperclass.kt b/compiler/testData/diagnostics/tests/override/ConflictingFunctionSignatureFromSuperclass.kt index 5bb76f9b84e..96da3f51c4a 100644 --- a/compiler/testData/diagnostics/tests/override/ConflictingFunctionSignatureFromSuperclass.kt +++ b/compiler/testData/diagnostics/tests/override/ConflictingFunctionSignatureFromSuperclass.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL open class Aaa() { fun foo() = 1 } diff --git a/compiler/testData/diagnostics/tests/override/clashesOnInheritance/conflictingInherited.fir.kt b/compiler/testData/diagnostics/tests/override/clashesOnInheritance/conflictingInherited.fir.kt new file mode 100644 index 00000000000..735011a923a --- /dev/null +++ b/compiler/testData/diagnostics/tests/override/clashesOnInheritance/conflictingInherited.fir.kt @@ -0,0 +1,31 @@ +// SKIP_TXT + +open class A { + fun some(s: String): T = null!! +} + +interface I { + fun some(text: String) = "" +} + +open class X1 : A(), I +open class X2 : X1() + +// for some reason no error in K1 +open class B { + fun some(s: String): T = null!! + + fun some(text: String) = "" +} + +open class X3 : B() +open class X4 : X3() + +open class C { + fun some(s: String): T = null!! +} + +open class X5 : C() { + fun some(text: String) = "" +} +open class X6 : X5() diff --git a/compiler/testData/diagnostics/tests/override/clashesOnInheritance/conflictingInherited.kt b/compiler/testData/diagnostics/tests/override/clashesOnInheritance/conflictingInherited.kt new file mode 100644 index 00000000000..d5ec9e6d5d3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/override/clashesOnInheritance/conflictingInherited.kt @@ -0,0 +1,31 @@ +// SKIP_TXT + +open class A { + fun some(s: String): T = null!! +} + +interface I { + fun some(text: String) = "" +} + +open class X1 : A(), I +open class X2 : X1() + +// for some reason no error in K1 +open class B { + fun some(s: String): T = null!! + + fun some(text: String) = "" +} + +open class X3 : B() +open class X4 : X3() + +open class C { + fun some(s: String): T = null!! +} + +open class X5 : C() { + fun some(text: String) = "" +} +open class X6 : X5() diff --git a/compiler/testData/diagnostics/tests/override/clashesOnInheritance/kt9550.fir.kt b/compiler/testData/diagnostics/tests/override/clashesOnInheritance/kt9550.fir.kt deleted file mode 100644 index 3adfcd33ed3..00000000000 --- a/compiler/testData/diagnostics/tests/override/clashesOnInheritance/kt9550.fir.kt +++ /dev/null @@ -1,13 +0,0 @@ -interface A { - fun foo() - fun bar() -} - -interface B { - fun foo() - fun bar() -} - -interface C1 : A, B { - override fun bar() -} diff --git a/compiler/testData/diagnostics/tests/override/clashesOnInheritance/kt9550.kt b/compiler/testData/diagnostics/tests/override/clashesOnInheritance/kt9550.kt index 8e70e835447..f2d0976d339 100644 --- a/compiler/testData/diagnostics/tests/override/clashesOnInheritance/kt9550.kt +++ b/compiler/testData/diagnostics/tests/override/clashesOnInheritance/kt9550.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL interface A { fun foo() fun bar() diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index b2c070969d8..1e22d333724 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -24135,6 +24135,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/override/clashesOnInheritance"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true); } + @Test + @TestMetadata("conflictingInherited.kt") + public void testConflictingInherited() throws Exception { + runTest("compiler/testData/diagnostics/tests/override/clashesOnInheritance/conflictingInherited.kt"); + } + @Test @TestMetadata("covariantOverrides.kt") public void testCovariantOverrides() throws Exception {