[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:
committed by
Space Team
parent
e0cb145c6b
commit
eda30ff704
@@ -108,6 +108,7 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
||||
|
||||
configuration.put(CommonConfigurationKeys.KLIB_NORMALIZE_ABSOLUTE_PATH, arguments.normalizeAbsolutePath)
|
||||
configuration.put(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME, arguments.renderInternalDiagnosticNames)
|
||||
configuration.put(CommonConfigurationKeys.PRODUCE_KLIB_SIGNATURES_CLASH_CHECKS, arguments.enableSignatureClashChecks)
|
||||
|
||||
return environment
|
||||
}
|
||||
|
||||
+19
-2
@@ -1,5 +1,6 @@
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext
|
||||
import org.jetbrains.kotlin.KtSourceFile
|
||||
import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode
|
||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.makeSerializedKlibMetadata
|
||||
@@ -10,9 +11,13 @@ import org.jetbrains.kotlin.backend.konan.driver.phases.FirOutput
|
||||
import org.jetbrains.kotlin.backend.konan.driver.phases.FirSerializerInput
|
||||
import org.jetbrains.kotlin.backend.konan.driver.phases.SerializerOutput
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.KonanIrModuleSerializer
|
||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.common.fir.reportToMessageCollector
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.backend.ConstValueProviderImpl
|
||||
import org.jetbrains.kotlin.fir.backend.extractFirDeclarations
|
||||
@@ -65,8 +70,10 @@ internal fun PhaseContext.firSerializerBase(
|
||||
}
|
||||
|
||||
val actualizedFirDeclarations = fir2IrInput?.irActualizedResult?.actualizedExpectDeclarations?.extractFirDeclarations()
|
||||
return serializeNativeModule(
|
||||
val diagnosticReporter = DiagnosticReporterFactory.createPendingReporter()
|
||||
val serializerOutput = serializeNativeModule(
|
||||
configuration = configuration,
|
||||
diagnosticReporter = diagnosticReporter,
|
||||
messageLogger = configuration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None,
|
||||
sourceFiles,
|
||||
usedResolvedLibraries?.map { it.library as KonanLibrary },
|
||||
@@ -95,6 +102,12 @@ internal fun PhaseContext.firSerializerBase(
|
||||
produceHeaderKlib,
|
||||
)
|
||||
}
|
||||
val renderDiagnosticNames = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME)
|
||||
diagnosticReporter.reportToMessageCollector(messageCollector, renderDiagnosticNames)
|
||||
if (diagnosticReporter.hasErrors) {
|
||||
throw KonanCompilationException("Compilation failed: there were errors during module serialization")
|
||||
}
|
||||
return serializerOutput
|
||||
}
|
||||
|
||||
class KotlinFileSerializedData(
|
||||
@@ -109,6 +122,7 @@ class KotlinFileSerializedData(
|
||||
|
||||
internal fun PhaseContext.serializeNativeModule(
|
||||
configuration: CompilerConfiguration,
|
||||
diagnosticReporter: DiagnosticReporter,
|
||||
messageLogger: IrMessageLogger,
|
||||
files: List<KtSourceFile>,
|
||||
dependencies: List<KonanLibrary>?,
|
||||
@@ -125,9 +139,11 @@ internal fun PhaseContext.serializeNativeModule(
|
||||
|
||||
val sourceBaseDirs = configuration[CommonConfigurationKeys.KLIB_RELATIVE_PATH_BASES] ?: emptyList()
|
||||
val absolutePathNormalization = configuration[CommonConfigurationKeys.KLIB_NORMALIZE_ABSOLUTE_PATH] ?: false
|
||||
val signatureClashChecks = configuration[CommonConfigurationKeys.PRODUCE_KLIB_SIGNATURES_CLASH_CHECKS] ?: true
|
||||
|
||||
val serializedIr = moduleFragment?.let {
|
||||
KonanIrModuleSerializer(
|
||||
KtDiagnosticReporterWithImplicitIrBasedContext(diagnosticReporter, configuration.languageVersionSettings),
|
||||
messageLogger,
|
||||
moduleFragment.irBuiltins,
|
||||
CompatibilityMode.CURRENT,
|
||||
@@ -135,7 +151,8 @@ internal fun PhaseContext.serializeNativeModule(
|
||||
sourceBaseDirs = sourceBaseDirs,
|
||||
languageVersionSettings = configuration.languageVersionSettings,
|
||||
bodiesOnlyForInlines = bodiesOnlyForInlines,
|
||||
skipPrivateApi = skipPrivateApi
|
||||
skipPrivateApi = skipPrivateApi,
|
||||
shouldCheckSignaturesOnUniqueness = signatureClashChecks,
|
||||
).serializedIrModule(moduleFragment)
|
||||
}
|
||||
|
||||
|
||||
+8
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.driver.phases
|
||||
|
||||
import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext
|
||||
import org.jetbrains.kotlin.backend.common.phaser.createSimpleNamedCompilerPhase
|
||||
import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode
|
||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer
|
||||
@@ -14,6 +15,7 @@ import org.jetbrains.kotlin.backend.konan.serialization.KonanIrModuleSerializer
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
|
||||
import org.jetbrains.kotlin.ir.util.IrMessageLogger
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
import org.jetbrains.kotlin.library.SerializedIrModule
|
||||
@@ -44,7 +46,12 @@ internal val SerializerPhase = createSimpleNamedCompilerPhase<PhaseContext, Seri
|
||||
val serializedIr = input.psiToIrOutput?.let {
|
||||
val ir = it.irModule
|
||||
KonanIrModuleSerializer(
|
||||
messageLogger, ir.irBuiltins,
|
||||
KtDiagnosticReporterWithImplicitIrBasedContext(
|
||||
DiagnosticReporterFactory.createPendingReporter(),
|
||||
config.languageVersionSettings
|
||||
),
|
||||
messageLogger,
|
||||
ir.irBuiltins,
|
||||
compatibilityMode = CompatibilityMode.CURRENT,
|
||||
normalizeAbsolutePaths = normalizeAbsolutePaths,
|
||||
sourceBaseDirs = relativePathBase,
|
||||
|
||||
Reference in New Issue
Block a user