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 ab49f0f1c37..413b0e1fc5e 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 @@ -588,11 +588,15 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { } val RETURN_TYPE_MISMATCH_ON_INHERITANCE by error(PositioningStrategy.DECLARATION_NAME) { - parameter>("classOrObject") parameter>("conflictingDeclaration1") parameter>("conflictingDeclaration2") } + val RETURN_TYPE_MISMATCH_BY_DELEGATION by error(PositioningStrategy.DECLARATION_NAME) { + parameter>("delegateDeclaration") + parameter>("baseDeclaration") + } + 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 72f1fd218b4..b7cf2b396e1 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 @@ -347,7 +347,8 @@ object FirErrors { val CANNOT_WEAKEN_ACCESS_PRIVILEGE by error3(SourceElementPositioningStrategies.VISIBILITY_MODIFIER) val CANNOT_CHANGE_ACCESS_PRIVILEGE by error3(SourceElementPositioningStrategies.VISIBILITY_MODIFIER) val OVERRIDING_FINAL_MEMBER by error2(SourceElementPositioningStrategies.OVERRIDE_MODIFIER) - val RETURN_TYPE_MISMATCH_ON_INHERITANCE by error3, FirCallableDeclaration<*>, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME) + val RETURN_TYPE_MISMATCH_ON_INHERITANCE by error2, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME) + val RETURN_TYPE_MISMATCH_BY_DELEGATION by error2, FirCallableDeclaration<*>>(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 09ac61f78c5..fead0001cc8 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 @@ -60,7 +60,6 @@ object FirImplementationMismatchChecker : FirClassChecker() { if (!(fir as FirCallableMemberDeclaration<*>).isAbstract) { implementations.add(fir) } -// val type = context.returnTypeCalculator.tryCalculateReturnType(intSymbol.fir).coneType } if (delegation != null || implementations.isNotEmpty()) { @@ -70,7 +69,10 @@ object FirImplementationMismatchChecker : FirClassChecker() { val (conflict, _) = withTypes.find { (_, type) -> !AbstractTypeChecker.isSubtypeOf(typeCheckerContext, methodType, type) } ?: return - dedupReporter.reportOn(source, FirErrors.RETURN_TYPE_MISMATCH_ON_INHERITANCE, declaration, method, conflict, context) + val error = + if (delegation != null) FirErrors.RETURN_TYPE_MISMATCH_BY_DELEGATION + else FirErrors.RETURN_TYPE_MISMATCH_ON_INHERITANCE + dedupReporter.reportOn(source, error, method, conflict, context) } else { //if there is no implementation, check that there can be any type compatible (subtype of) with all var clash: Pair, FirCallableDeclaration<*>>? = null @@ -84,7 +86,7 @@ object FirImplementationMismatchChecker : FirClassChecker() { } } clash?.takeIf { !compatible }?.let { (m1, m2) -> - dedupReporter.reportOn(source, FirErrors.RETURN_TYPE_MISMATCH_ON_INHERITANCE, declaration, m1, m2, context) + dedupReporter.reportOn(source, FirErrors.RETURN_TYPE_MISMATCH_ON_INHERITANCE, m1, m2, context) } } } 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 e8a94fddd59..be94a601e81 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 @@ -299,6 +299,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RESULT_TYPE_MISMA import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_NOT_ALLOWED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_TYPE_MISMATCH +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_TYPE_MISMATCH_BY_DELEGATION +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_TYPE_MISMATCH_ON_INHERITANCE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_TYPE_MISMATCH_ON_OVERRIDE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_CLASS_CONSTRUCTOR_CALL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_SUPERTYPE @@ -935,6 +937,20 @@ class FirDefaultErrorMessages { "Inner class of generic class extending 'Throwable' is prohibited" ) + map.put( + RETURN_TYPE_MISMATCH_ON_INHERITANCE, + "''{0}'' clashes with ''{1}'': return types are incompatible", + NAME, + NAME + ) + + map.put( + RETURN_TYPE_MISMATCH_BY_DELEGATION, + "Type of ''{0}'' is not a subtype of overridden by delegation ''{1}''", + NAME, + 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/delegation/Delegation_ClashingFunctions.fir.kt b/compiler/testData/diagnostics/tests/delegation/Delegation_ClashingFunctions.fir.kt index cb753f3700b..6d3e8e4011f 100644 --- a/compiler/testData/diagnostics/tests/delegation/Delegation_ClashingFunctions.fir.kt +++ b/compiler/testData/diagnostics/tests/delegation/Delegation_ClashingFunctions.fir.kt @@ -10,9 +10,9 @@ interface Three { public fun foo(): String } -class Test123(val v1: One, val v2: Two, val v3: Three) : One by v1, Two by v2, Three by v3 { } -class Test132(val v1: One, val v2: Two, val v3: Three) : One by v1, Three by v3, Two by v2 { } +class Test123(val v1: One, val v2: Two, val v3: Three) : One by v1, Two by v2, Three by v3 { } +class Test132(val v1: One, val v2: Two, val v3: Three) : One by v1, Three by v3, Two by v2 { } class Test312(val v1: One, val v2: Two, val v3: Three) : Three by v3, One by v1, Two by v2 { } class Test321(val v1: One, val v2: Two, val v3: Three) : Three by v3, Two by v2, One by v1 { } -class Test231(val v1: One, val v2: Two, val v3: Three) : Two by v2, Three by v3, One by v1 { } -class Test213(val v1: One, val v2: Two, val v3: Three) : Two by v2, One by v1, Three by v3 { } +class Test231(val v1: One, val v2: Two, val v3: Three) : Two by v2, Three by v3, One by v1 { } +class Test213(val v1: One, val v2: Two, val v3: Three) : Two by v2, One by v1, Three by v3 { } diff --git a/compiler/testData/diagnostics/tests/delegation/clashes/returnTypeMismatch.fir.kt b/compiler/testData/diagnostics/tests/delegation/clashes/returnTypeMismatch.fir.kt index bc69e355a11..9f0da27c818 100644 --- a/compiler/testData/diagnostics/tests/delegation/clashes/returnTypeMismatch.fir.kt +++ b/compiler/testData/diagnostics/tests/delegation/clashes/returnTypeMismatch.fir.kt @@ -32,28 +32,28 @@ class CGeneric : IGeneric { } } -abstract class Test1 : IStr by CStr(), IInt +abstract class Test1 : IStr by CStr(), IInt -abstract class Test2 : IStr, IInt by CInt() +abstract class Test2 : IStr, IInt by CInt() -abstract class Test3 : IStr by CStr(), IInt by CInt() +abstract class Test3 : IStr by CStr(), IInt by CInt() abstract class Test4 : IStr by CStr(), IGeneric abstract class Test5 : IStr by CStr(), IGeneric -abstract class Test6 : IStr by CStr(), IGeneric +abstract class Test6 : IStr by CStr(), IGeneric abstract class Test7 : IGeneric by CGeneric(), IStr -abstract class Test8 : IGeneric by CGeneric(), IInt +abstract class Test8 : IGeneric by CGeneric(), IInt // Can't test due to https://youtrack.jetbrains.com/issue/KT-10258 // abstract class Test9 : IGeneric by CGeneric(), IGeneric -abstract class Test10 : IInt by CInt(), IStr by CStr(), IAny by CAny() +abstract class Test10 : IInt by CInt(), IStr by CStr(), IAny by CAny() -abstract class Test11 : IInt, IStr by CStr(), IAny by CAny() +abstract class Test11 : IInt, IStr by CStr(), IAny by CAny() -abstract class Test12 : IInt, IStr, IAny by CAny() +abstract class Test12 : IInt, IStr, IAny by CAny() diff --git a/compiler/testData/diagnostics/tests/delegation/covariantOverrides/fromClass.fir.kt b/compiler/testData/diagnostics/tests/delegation/covariantOverrides/fromClass.fir.kt index 8f384cd3e92..feedc7d930e 100644 --- a/compiler/testData/diagnostics/tests/delegation/covariantOverrides/fromClass.fir.kt +++ b/compiler/testData/diagnostics/tests/delegation/covariantOverrides/fromClass.fir.kt @@ -6,7 +6,7 @@ open class IDerived1 : IBase1 { override fun foo(): String = "1" } -class Broken1(val b: IBase1) : IBase1 by b, IDerived1() +class Broken1(val b: IBase1) : IBase1 by b, IDerived1() interface IBase2 { val foo: Any diff --git a/compiler/testData/diagnostics/tests/delegation/covariantOverrides/irrelevant.fir.kt b/compiler/testData/diagnostics/tests/delegation/covariantOverrides/irrelevant.fir.kt index a864c7c4a2f..02972f61725 100644 --- a/compiler/testData/diagnostics/tests/delegation/covariantOverrides/irrelevant.fir.kt +++ b/compiler/testData/diagnostics/tests/delegation/covariantOverrides/irrelevant.fir.kt @@ -6,7 +6,7 @@ interface IDerived1 { fun foo(): String } -class Broken1(val b: IBase1) : IBase1 by b, IDerived1 +class Broken1(val b: IBase1) : IBase1 by b, IDerived1 interface IBase2 { val foo: Any diff --git a/compiler/testData/diagnostics/tests/delegation/covariantOverrides/kt13952.fir.kt b/compiler/testData/diagnostics/tests/delegation/covariantOverrides/kt13952.fir.kt index 127b8af6c69..100585fdc5b 100644 --- a/compiler/testData/diagnostics/tests/delegation/covariantOverrides/kt13952.fir.kt +++ b/compiler/testData/diagnostics/tests/delegation/covariantOverrides/kt13952.fir.kt @@ -10,7 +10,7 @@ object AImpl : IA { override fun foo() = 42 } -open class C : IA by AImpl, IB +open class C : IA by AImpl, IB class D : C() { override fun foo(): Double = 3.14 diff --git a/compiler/testData/diagnostics/tests/delegation/covariantOverrides/simple.fir.kt b/compiler/testData/diagnostics/tests/delegation/covariantOverrides/simple.fir.kt index 5dd07749362..a4b93100dcf 100644 --- a/compiler/testData/diagnostics/tests/delegation/covariantOverrides/simple.fir.kt +++ b/compiler/testData/diagnostics/tests/delegation/covariantOverrides/simple.fir.kt @@ -6,7 +6,7 @@ interface IDerived1 : IBase1 { override fun foo(): String } -class Broken1(val b: IBase1) : IBase1 by b, IDerived1 +class Broken1(val b: IBase1) : IBase1 by b, IDerived1 interface IBase2 { val foo: Any 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 72fabe16d63..d348e5ca291 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 @@ -1654,9 +1654,16 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert } add(FirErrors.RETURN_TYPE_MISMATCH_ON_INHERITANCE) { firDiagnostic -> ReturnTypeMismatchOnInheritanceImpl( - firSymbolBuilder.classifierBuilder.buildClassLikeSymbol(firDiagnostic.a), + firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a as FirCallableDeclaration), + firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.b as FirCallableDeclaration), + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } + add(FirErrors.RETURN_TYPE_MISMATCH_BY_DELEGATION) { firDiagnostic -> + ReturnTypeMismatchByDelegationImpl( + firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a as FirCallableDeclaration), firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.b as FirCallableDeclaration), - firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.c as FirCallableDeclaration), firDiagnostic as FirPsiDiagnostic<*>, token, ) 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 8742ad45275..7e48c8e6baa 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 @@ -1173,11 +1173,16 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract class ReturnTypeMismatchOnInheritance : KtFirDiagnostic() { override val diagnosticClass get() = ReturnTypeMismatchOnInheritance::class - abstract val classOrObject: KtClassLikeSymbol abstract val conflictingDeclaration1: KtCallableSymbol abstract val conflictingDeclaration2: KtCallableSymbol } + abstract class ReturnTypeMismatchByDelegation : KtFirDiagnostic() { + override val diagnosticClass get() = ReturnTypeMismatchByDelegation::class + abstract val delegateDeclaration: KtCallableSymbol + abstract val baseDeclaration: KtCallableSymbol + } + 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 1c6d1f316a1..8fb1b2d0739 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 @@ -1884,7 +1884,6 @@ internal class OverridingFinalMemberImpl( } internal class ReturnTypeMismatchOnInheritanceImpl( - override val classOrObject: KtClassLikeSymbol, override val conflictingDeclaration1: KtCallableSymbol, override val conflictingDeclaration2: KtCallableSymbol, firDiagnostic: FirPsiDiagnostic<*>, @@ -1893,6 +1892,15 @@ internal class ReturnTypeMismatchOnInheritanceImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class ReturnTypeMismatchByDelegationImpl( + override val delegateDeclaration: KtCallableSymbol, + override val baseDeclaration: KtCallableSymbol, + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.ReturnTypeMismatchByDelegation(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class AbstractMemberNotImplementedImpl( override val classOrObject: KtClassLikeSymbol, override val missingDeclaration: KtCallableSymbol,