[klib] Implement diagnostics for clashing KLIB signatures

Now, we detect clashing signatures during serialization to KLIB and
report a compiler error if two or more declarations have the same
`IdSignature`

For example, for the following code:
```kotlin
@Deprecated("", level = DeprecationLevel.HIDDEN)
fun foo(): String = ""

fun foo(): Int = 0
```

the compiler will produce this diagnostic:
```
e: main.kt:1:1 Platform declaration clash: The following declarations
       have the same KLIB signature (/foo|foo(){}[0]):
    fun foo(): String defined in root package
    fun foo(): Int defined in root package
e: main.kt:4:1 Platform declaration clash: The following declarations
       have the same KLIB signature (/foo|foo(){}[0]):
    fun foo(): String defined in root package
    fun foo(): Int defined in root package
```

Note that we report this diagnostic during serialization and not earlier
(e.g., in fir2ir) for more robustness, so ensure that we check
exactly the signatures that will be written to a KLIB.
If we later introduce some annotation for customizing a declaration's
signature (e.g., for preserving binary compatibility), this
diagnostic will continue to work as expected.

^KT-63670 Fixed
This commit is contained in:
Sergej Jaskiewicz
2023-12-15 20:05:02 +01:00
committed by Space Team
parent e0cb145c6b
commit eda30ff704
27 changed files with 366 additions and 98 deletions
@@ -11,6 +11,7 @@ import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext
import org.jetbrains.kotlin.KtPsiSourceFile
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.backend.common.linkage.issues.checkNoUnboundSymbols
@@ -37,7 +38,6 @@ import org.jetbrains.kotlin.ir.backend.js.*
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrModuleSerializer
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.collectExportedNames
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
@@ -529,7 +529,11 @@ class GenerateIrRuntime {
private fun doSerializeIrModule(module: IrModuleFragment): SerializedIrModule {
val serializedIr = JsIrModuleSerializer(
return JsIrModuleSerializer(
KtDiagnosticReporterWithImplicitIrBasedContext(
DiagnosticReporterFactory.createPendingReporter(),
configuration.languageVersionSettings,
),
IrMessageLogger.None,
module.irBuiltins,
CompatibilityMode.CURRENT,
@@ -537,7 +541,6 @@ class GenerateIrRuntime {
emptyList(),
configuration.languageVersionSettings,
).serializedIrModule(module)
return serializedIr
}
private fun doWriteIrModuleToStorage(serializedIrModule: SerializedIrModule, writer: KotlinLibraryOnlyIrWriter) {
@@ -211,6 +211,15 @@ fun main(args: Array<String>) {
model("debug/localVariables")
}
testClass<AbstractFirPsiJsDiagnosticWithBackendTest>(suiteTestClassName = "FirPsiJsKlibDiagnosticsTestGenerated") {
model(
relativeRootPath = "diagnostics/klibSerializationTests",
pattern = "^([^_](.+))\\.kt$",
excludedPattern = excludedFirTestdataPattern,
targetBackend = TargetBackend.JS_IR
)
}
testClass<AbstractFirPsiJsDiagnosticTest>(suiteTestClassName = "FirPsiJsOldFrontendDiagnosticsTestGenerated") {
model(
relativeRootPath = "diagnostics/testsWithJsStdLib",
@@ -164,5 +164,7 @@ fun <
irHandlersStep()
facadeStep(backendFacade)
klibArtifactsHandlersStep()
klibArtifactsHandlersStep {
useHandlers(::JsBackendDiagnosticsHandler)
}
}