diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 072a510db5b..bfd4f05cb38 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -617,6 +617,10 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { parameter>("baseDeclaration") } + val CONFLICTING_INHERITED_MEMBERS by error(PositioningStrategy.DECLARATION_NAME) { + parameter>>("conflictingDeclarations") + } + val ABSTRACT_MEMBER_NOT_IMPLEMENTED by error(PositioningStrategy.DECLARATION_NAME) { parameter("classOrObject") parameter("missingDeclaration") diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 7d1eade95a3..691c8df3e64 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -353,6 +353,7 @@ object FirErrors { val RETURN_TYPE_MISMATCH_BY_DELEGATION by error2, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME) val PROPERTY_TYPE_MISMATCH_BY_DELEGATION by error2, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME) val VAR_OVERRIDDEN_BY_VAL_BY_DELEGATION by error2, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME) + val CONFLICTING_INHERITED_MEMBERS by error1>>(SourceElementPositioningStrategies.DECLARATION_NAME) val ABSTRACT_MEMBER_NOT_IMPLEMENTED by error2(SourceElementPositioningStrategies.DECLARATION_NAME) val ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED by error2(SourceElementPositioningStrategies.DECLARATION_NAME) val INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER by error2(SourceElementPositioningStrategies.DECLARATION_NAME) 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 0f908b57c0e..f7aad3f0924 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 @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.impl.deduplicating import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.typeContext @@ -21,6 +22,7 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinErrorType import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext import org.jetbrains.kotlin.fir.types.coneType +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.AbstractTypeChecker object FirImplementationMismatchChecker : FirClassChecker() { @@ -46,6 +48,7 @@ object FirImplementationMismatchChecker : FirClassChecker() { checkInheritanceClash(declaration, context, dedupReporter, typeCheckerContext, it) checkValOverrideVar(declaration, context, dedupReporter, it) } + checkConflictingMembers(declaration, context, dedupReporter, classScope, name) } } @@ -154,4 +157,34 @@ object FirImplementationMismatchChecker : FirClassChecker() { reporter.reportOn(containingClass.source, FirErrors.VAR_OVERRIDDEN_BY_VAL_BY_DELEGATION, delegatedVal.fir, baseVar.fir, context) } } + + private fun checkConflictingMembers( + containingClass: FirClass<*>, + context: CheckerContext, + reporter: DiagnosticReporter, + scope: FirTypeScope, + name: Name + ) { + 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)?.fir } + !declaredInThisClass -> allFunctions.add(sym.fir) + } + } + + val sameArgumentGroups = allFunctions.groupBy { function -> + function.valueParameters.map { it.returnTypeRef.coneType } + }.values + + val clash = sameArgumentGroups.mapNotNull { fs -> + fs.zipWithNext().find { (m1, m2) -> + m1.isSuspend != m2.isSuspend || m1.typeParameters.size != m2.typeParameters.size + } + }.firstOrNull() ?: return + + reporter.reportOn(containingClass.source, FirErrors.CONFLICTING_INHERITED_MEMBERS, clash.toList(), context) + } } \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index 0494ab590a2..887871d941f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages import org.jetbrains.kotlin.diagnostics.rendering.LanguageFeatureMessageRenderer import org.jetbrains.kotlin.diagnostics.rendering.Renderers.RENDER_POSITION_VARIANCE +import org.jetbrains.kotlin.diagnostics.rendering.Renderers.commaSeparated import org.jetbrains.kotlin.diagnostics.rendering.Renderers.STRING import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.AMBIGUOUS_CALLS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.DECLARATION_NAME @@ -76,6 +77,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMPONENT_FUNCTIO import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONDITION_TYPE_MISMATCH import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_IMPORT +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_INHERITED_MEMBERS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_OVERLOADS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_PROJECTION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION @@ -983,6 +985,12 @@ class FirDefaultErrorMessages { NAME ) + map.put( + CONFLICTING_INHERITED_MEMBERS, + "{0} inherits conflicting members: {1}", + commaSeparated(NAME) + ) + // Redeclarations map.put(MANY_COMPANION_OBJECTS, "Only one companion object is allowed per class") map.put(CONFLICTING_OVERLOADS, "Conflicting overloads: {0}", SYMBOLS) // * diff --git a/compiler/testData/diagnostics/tests/annotations/rendering/notImplementedMembers.fir.kt b/compiler/testData/diagnostics/tests/annotations/rendering/notImplementedMembers.fir.kt index 1e7e9872d7b..9ac88ba867c 100644 --- a/compiler/testData/diagnostics/tests/annotations/rendering/notImplementedMembers.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/rendering/notImplementedMembers.fir.kt @@ -15,7 +15,7 @@ interface B { fun a(@An arg: @An Int) } -interface C : A, B +interface C : A, B @An abstract class D { diff --git a/compiler/testData/diagnostics/tests/override/clashesOnInheritance/kt9550.fir.kt b/compiler/testData/diagnostics/tests/override/clashesOnInheritance/kt9550.fir.kt index 054e69b9189..3adfcd33ed3 100644 --- a/compiler/testData/diagnostics/tests/override/clashesOnInheritance/kt9550.fir.kt +++ b/compiler/testData/diagnostics/tests/override/clashesOnInheritance/kt9550.fir.kt @@ -8,6 +8,6 @@ interface B { fun bar() } -interface C1 : A, B { +interface C1 : A, B { override fun bar() } diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/mixingSuspendability.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/mixingSuspendability.fir.kt index 1d9f1e9478a..9872eaf8f64 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/mixingSuspendability.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/mixingSuspendability.fir.kt @@ -1,6 +1,6 @@ interface AsyncVal { suspend fun getVal(): Int = 1} interface SyncVal { fun getVal(): Int = 1 } -class MixSuspend : AsyncVal, SyncVal { +class MixSuspend : AsyncVal, SyncVal { } 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 50a3873cf0c..29ce586434b 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 @@ -20624,7 +20624,7 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { @Test @TestMetadata("kt13355viaJava.kt") - public void testKt13355viaJava1111() throws Exception { + public void testKt13355viaJava() throws Exception { runTest("compiler/testData/diagnostics/tests/override/clashesOnInheritance/kt13355viaJava.kt"); } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt index 6b186432e0f..77f99651ff0 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -1700,6 +1700,15 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.CONFLICTING_INHERITED_MEMBERS) { firDiagnostic -> + ConflictingInheritedMembersImpl( + firDiagnostic.a.map { firCallableDeclaration -> + firSymbolBuilder.callableBuilder.buildCallableSymbol(firCallableDeclaration as FirCallableDeclaration) + }, + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirErrors.ABSTRACT_MEMBER_NOT_IMPLEMENTED) { firDiagnostic -> AbstractMemberNotImplementedImpl( firSymbolBuilder.classifierBuilder.buildClassLikeSymbol(firDiagnostic.a), diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt index 0abc02d2311..c2e62734637 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt @@ -1207,6 +1207,11 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val baseDeclaration: KtCallableSymbol } + abstract class ConflictingInheritedMembers : KtFirDiagnostic() { + override val diagnosticClass get() = ConflictingInheritedMembers::class + abstract val conflictingDeclarations: List + } + abstract class AbstractMemberNotImplemented : KtFirDiagnostic() { override val diagnosticClass get() = AbstractMemberNotImplemented::class abstract val classOrObject: KtClassLikeSymbol diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index ef2f850d24c..826a4e933dd 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -1937,6 +1937,14 @@ internal class VarOverriddenByValByDelegationImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class ConflictingInheritedMembersImpl( + override val conflictingDeclarations: List, + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.ConflictingInheritedMembers(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class AbstractMemberNotImplementedImpl( override val classOrObject: KtClassLikeSymbol, override val missingDeclaration: KtCallableSymbol,