diff --git a/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/HLDiagnosticConverter.kt b/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/HLDiagnosticConverter.kt index 1112bed8ff1..7e9ada2f624 100644 --- a/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/HLDiagnosticConverter.kt +++ b/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/HLDiagnosticConverter.kt @@ -361,6 +361,7 @@ internal object FirToKtConversionCreator { FqName::class, ClassId::class, FirModuleData::class, + ExpectActualCompatibility::class, ExpectActualCompatibility.Incompatible::class, DeprecationInfo::class, ApiVersion::class, diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index e3cff078d1e..05a19202422 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -3215,8 +3215,8 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert NoActualForExpectImpl( firSymbolBuilder.buildSymbol(firDiagnostic.a), firDiagnostic.b, - firDiagnostic.c.mapKeys { (incompatible, _) -> - incompatible + firDiagnostic.c.mapKeys { (expectActualCompatibility, _) -> + expectActualCompatibility }.mapValues { (_, collection) -> collection.map { firBasedSymbol -> firSymbolBuilder.buildSymbol(firBasedSymbol) @@ -3229,8 +3229,8 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert add(FirErrors.ACTUAL_WITHOUT_EXPECT) { firDiagnostic -> ActualWithoutExpectImpl( firSymbolBuilder.buildSymbol(firDiagnostic.a), - firDiagnostic.b.mapKeys { (incompatible, _) -> - incompatible + firDiagnostic.b.mapKeys { (expectActualCompatibility, _) -> + expectActualCompatibility }.mapValues { (_, collection) -> collection.map { firBasedSymbol -> firSymbolBuilder.buildSymbol(firBasedSymbol) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index fc91b37d454..e95083f3e77 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -80,6 +80,7 @@ import org.jetbrains.kotlin.psi.KtWhenEntry import org.jetbrains.kotlin.psi.KtWhenExpression import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget import org.jetbrains.kotlin.resolve.deprecation.DeprecationInfo +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible import org.jetbrains.kotlin.types.Variance @@ -2262,13 +2263,13 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = NoActualForExpect::class abstract val declaration: KtSymbol abstract val module: FirModuleData - abstract val compatibility: Map>, List> + abstract val compatibility: Map>, List> } abstract class ActualWithoutExpect : KtFirDiagnostic() { override val diagnosticClass get() = ActualWithoutExpect::class abstract val declaration: KtSymbol - abstract val compatibility: Map>, List> + abstract val compatibility: Map>, List> } abstract class AmbiguousActuals : KtFirDiagnostic() { diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index b7a056b9261..9ce30cf19c9 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -81,6 +81,7 @@ import org.jetbrains.kotlin.psi.KtWhenEntry import org.jetbrains.kotlin.psi.KtWhenExpression import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget import org.jetbrains.kotlin.resolve.deprecation.DeprecationInfo +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible import org.jetbrains.kotlin.types.Variance @@ -2727,14 +2728,14 @@ internal class ExpectedFunctionSourceWithDefaultArgumentsNotFoundImpl( internal class NoActualForExpectImpl( override val declaration: KtSymbol, override val module: FirModuleData, - override val compatibility: Map>, List>, + override val compatibility: Map>, List>, override val firDiagnostic: KtPsiDiagnostic, override val token: KtLifetimeToken, ) : KtFirDiagnostic.NoActualForExpect(), KtAbstractFirDiagnostic internal class ActualWithoutExpectImpl( override val declaration: KtSymbol, - override val compatibility: Map>, List>, + override val compatibility: Map>, List>, override val firDiagnostic: KtPsiDiagnostic, override val token: KtLifetimeToken, ) : KtFirDiagnostic.ActualWithoutExpect(), KtAbstractFirDiagnostic diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java index 3cdd0b3d85d..212fa6b2028 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java @@ -556,6 +556,12 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/intermediateActualHasAdditionalSupertypes.kt"); } + @Test + @TestMetadata("kt57320.kt") + public void testKt57320() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.kt"); + } + @Test @TestMetadata("kt-55570.kt") public void testKt_55570() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java index 4452703e208..08d3fd7ab62 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java @@ -556,6 +556,12 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/intermediateActualHasAdditionalSupertypes.kt"); } + @Test + @TestMetadata("kt57320.kt") + public void testKt57320() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.kt"); + } + @Test @TestMetadata("kt-55570.kt") public void testKt_55570() throws Exception { 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 16a41922ffc..436fcf4a7a8 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 @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget import org.jetbrains.kotlin.resolve.deprecation.DeprecationInfo +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible import org.jetbrains.kotlin.types.Variance import kotlin.properties.PropertyDelegateProvider @@ -1089,12 +1090,12 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val NO_ACTUAL_FOR_EXPECT by error(PositioningStrategy.INCOMPATIBLE_DECLARATION) { parameter("declaration") parameter("module") - parameter, Collection>>("compatibility") + parameter, Collection>>("compatibility") } val ACTUAL_WITHOUT_EXPECT by error { parameter("declaration") - parameter, Collection>>("compatibility") + parameter, Collection>>("compatibility") } val AMBIGUOUS_ACTUALS by error(PositioningStrategy.INCOMPATIBLE_DECLARATION) { 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 0fc7265b6e5..d69b540d312 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 @@ -100,6 +100,7 @@ import org.jetbrains.kotlin.psi.KtWhenEntry import org.jetbrains.kotlin.psi.KtWhenExpression import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget import org.jetbrains.kotlin.resolve.deprecation.DeprecationInfo +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible import org.jetbrains.kotlin.types.Variance @@ -593,8 +594,8 @@ object FirErrors { val ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS by error0() val ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE by error1>() val EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND by error0() - val NO_ACTUAL_FOR_EXPECT by error3, FirModuleData, Map>, Collection>>>(SourceElementPositioningStrategies.INCOMPATIBLE_DECLARATION) - val ACTUAL_WITHOUT_EXPECT by error2, Map>, Collection>>>() + val NO_ACTUAL_FOR_EXPECT by error3, FirModuleData, Map>, Collection>>>(SourceElementPositioningStrategies.INCOMPATIBLE_DECLARATION) + val ACTUAL_WITHOUT_EXPECT by error2, Map>, Collection>>>() val AMBIGUOUS_ACTUALS by error2, Collection>>(SourceElementPositioningStrategies.INCOMPATIBLE_DECLARATION) val AMBIGUOUS_EXPECTS by error2, Collection>(SourceElementPositioningStrategies.INCOMPATIBLE_DECLARATION) val NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS by error2, List, Map>, Collection>>>>>(SourceElementPositioningStrategies.ACTUAL_DECLARATION_NAME) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirActualCallableDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirActualCallableDeclarationChecker.kt index c8d1b649a5c..396b5eada68 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirActualCallableDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirActualCallableDeclarationChecker.kt @@ -58,14 +58,13 @@ object FirActualCallableDeclarationChecker : FirCallableDeclarationChecker() { context.session ) ) { - @Suppress("UNCHECKED_CAST") reporter.reportOn( callableDeclaration.source, FirErrors.ACTUAL_WITHOUT_EXPECT, actualFunctionSymbol, - actualFunctionSymbol.expectForActual as Map>, Collection>>, + actualFunctionSymbol.expectForActual as Map>, Collection>>, context ) } } -} \ No newline at end of file +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt index ceadb83623c..9aa80ba43fe 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt @@ -93,12 +93,11 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() { } Compatible !in compatibilityToMembersMap -> { - @Suppress("UNCHECKED_CAST") reporter.reportOn( source, FirErrors.ACTUAL_WITHOUT_EXPECT, symbol, - compatibilityToMembersMap as Map>, Collection>>, + compatibilityToMembersMap, context ) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirPlatformIncompatibilityDiagnosticRenderer.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirPlatformIncompatibilityDiagnosticRenderer.kt index 8b09ad5ce90..5928fc852a4 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirPlatformIncompatibilityDiagnosticRenderer.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirPlatformIncompatibilityDiagnosticRenderer.kt @@ -18,13 +18,14 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics import org.jetbrains.kotlin.diagnostics.rendering.ContextIndependentParameterRenderer import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible class FirPlatformIncompatibilityDiagnosticRenderer( private val mode: MultiplatformDiagnosticRenderingMode -) : ContextIndependentParameterRenderer>, Collection>>> { +) : ContextIndependentParameterRenderer>, Collection>>> { override fun render( - obj: Map>, Collection>>, + obj: Map>, Collection>>, ): String { if (obj.isEmpty()) return "" @@ -80,33 +81,33 @@ open class MultiplatformDiagnosticRenderingMode { } private fun StringBuilder.renderIncompatibilityInformation( - map: Map>, Collection>>, + map: Map>, Collection>>, indent: String, mode: MultiplatformDiagnosticRenderingMode ) { - for ((incompatibility, descriptors) in map) { + for ((compatibility, descriptors) in map) { append(indent) append("The following declaration") if (descriptors.size == 1) append(" is") else append("s are") append(" incompatible") - incompatibility.reason?.let { append(" because $it") } + (compatibility as? Incompatible)?.reason?.let { append(" because $it") } append(":") mode.renderList(this, descriptors.map { descriptor -> { mode.renderSymbol(this, descriptor, indent) } }) - if (incompatibility is Incompatible.ClassScopes) { + if (compatibility is Incompatible.ClassScopes) { append(indent) append("No actual members are found for expected members listed below:") mode.newLine(this) - renderIncompatibleClassScopes(incompatibility.unfulfilled, indent, mode) + renderIncompatibleClassScopes(compatibility.unfulfilled, indent, mode) } } } private fun StringBuilder.renderIncompatibleClassScopes( - unfulfilled: List, Map>, Collection>>>>, + unfulfilled: List, Map>, Collection>>>>, indent: String, mode: MultiplatformDiagnosticRenderingMode ) { diff --git a/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.fir.kt new file mode 100644 index 00000000000..cb24a89785e --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.fir.kt @@ -0,0 +1,42 @@ +// !LANGUAGE: +MultiPlatformProjects + +// MODULE: common +// TARGET_PLATFORM: Common + +// FILE: StringValue.kt +expect class StringValue + +expect fun StringValue.plus(other: String): StringValue + +// MODULE: commonJS()()(common) +// TARGET_PLATFORM: JS + +// FILE: StringValue.kt +actual class StringValue(val value: String) + +actual fun StringValue.plus(other: String) = StringValue(this.value + other) + +// MODULE: intermediate()()(common) +// TARGET_PLATFORM: Common + +// FILE: StringDemoInterface.kt +expect interface StringDemoInterface + +interface KotlinXStringDemoInterface { + val value: String +} + +expect fun StringDemoInterface.plusK(): String + +// MODULE: js()()(common, intermediate) +// TARGET_PLATFORM: JS + +// FILE: StringDemoInterface.kt +actual typealias StringDemoInterface = KotlinXStringDemoInterface + +; The following declaration is incompatible: expect fun StringDemoInterface.plusK(): String")!>actual fun StringDemoInterface.plusK() = StringValue(value).plus("K").value + +// FILE: main.kt +class StringDemo(override val value: String) : StringDemoInterface + +fun box() = StringDemo("O").plusK() diff --git a/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.kt b/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.kt new file mode 100644 index 00000000000..067ecb08938 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.kt @@ -0,0 +1,42 @@ +// !LANGUAGE: +MultiPlatformProjects + +// MODULE: common +// TARGET_PLATFORM: Common + +// FILE: StringValue.kt +expect class StringValue + +expect fun StringValue.plus(other: String): StringValue + +// MODULE: commonJS()()(common) +// TARGET_PLATFORM: JS + +// FILE: StringValue.kt +actual class StringValue(val value: String) + +actual fun StringValue.plus(other: String) = StringValue(this.value + other) + +// MODULE: intermediate()()(common) +// TARGET_PLATFORM: Common + +// FILE: StringDemoInterface.kt +expect interface StringDemoInterface + +interface KotlinXStringDemoInterface { + val value: String +} + +expect fun StringDemoInterface.plusK(): String + +// MODULE: js()()(common, intermediate) +// TARGET_PLATFORM: JS + +// FILE: StringDemoInterface.kt +actual typealias StringDemoInterface = KotlinXStringDemoInterface + +actual fun StringDemoInterface.plusK() = StringValue(value).plus("K").value + +// FILE: main.kt +class StringDemo(override val value: String) : StringDemoInterface + +fun box() = StringDemo("O").plusK() 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 70a3c5c4953..22622a1044d 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 @@ -22257,6 +22257,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/intermediateActualHasAdditionalSupertypes.kt"); } + @Test + @TestMetadata("kt57320.kt") + public void testKt57320() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.kt"); + } + @Test @TestMetadata("kt-55570.kt") public void testKt_55570() throws Exception {