diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/linkage/partial/PartialLinkageUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/linkage/partial/PartialLinkageUtils.kt index 071928e0138..1fecb165fd9 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/linkage/partial/PartialLinkageUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/linkage/partial/PartialLinkageUtils.kt @@ -44,7 +44,7 @@ object PartialLinkageUtils { override val name = "" } - fun defaultLocationWithoutPath() = IrMessageLogger.Location(name, UNDEFINED_LINE_NUMBER, UNDEFINED_COLUMN_NUMBER) + fun defaultLocationWithoutPath() = PartialLinkageLogger.Location(name, /* no path */ "", UNDEFINED_LINE_NUMBER, UNDEFINED_COLUMN_NUMBER) companion object { fun determineModuleFor(declaration: IrDeclaration): Module = determineFor( @@ -60,18 +60,17 @@ object PartialLinkageUtils { sealed interface File { val module: Module - fun computeLocationForOffset(offset: Int): IrMessageLogger.Location + fun computeLocationForOffset(offset: Int): PartialLinkageLogger.Location data class IrBased(private val file: IrFile) : File { override val module = Module.Real(file.module.name) - override fun computeLocationForOffset(offset: Int): IrMessageLogger.Location { - val lineNumber = if (offset == UNDEFINED_OFFSET) UNDEFINED_LINE_NUMBER else file.fileEntry.getLineNumber(offset) + 1 // since humans count from 1, not 0 - val columnNumber = if (offset == UNDEFINED_OFFSET) UNDEFINED_COLUMN_NUMBER else file.fileEntry.getColumnNumber(offset) + 1 - - // TODO: should module name still be added here? - return IrMessageLogger.Location("${module.name} @ ${file.fileEntry.name}", lineNumber, columnNumber) - } + override fun computeLocationForOffset(offset: Int) = PartialLinkageLogger.Location( + moduleName = module.name, + filePath = file.fileEntry.name, + lineNumber = if (offset == UNDEFINED_OFFSET) UNDEFINED_LINE_NUMBER else file.fileEntry.getLineNumber(offset) + 1, // since humans count from 1, not 0 + columnNumber = if (offset == UNDEFINED_OFFSET) UNDEFINED_COLUMN_NUMBER else file.fileEntry.getColumnNumber(offset) + 1 + ) } class LazyIrBased(packageFragmentDescriptor: PackageFragmentDescriptor) : File { @@ -134,3 +133,34 @@ object PartialLinkageUtils { } } } + +// A workaround for KT-58837 until KT-58904 is fixed. TODO: Merge with IrMessageLogger. +class PartialLinkageLogger(private val irLogger: IrMessageLogger, logLevel: PartialLinkageLogLevel) { + class Location(val moduleName: String, val filePath: String, val lineNumber: Int, val columnNumber: Int) { + fun render(): StringBuilder = StringBuilder().apply { + append(moduleName) + if (filePath.isNotEmpty()) { + append(" @ ").append(filePath) + if (lineNumber != UNDEFINED_LINE_NUMBER && columnNumber != UNDEFINED_COLUMN_NUMBER) { + append(':').append(lineNumber).append(':').append(columnNumber) + } + } + } + + override fun toString() = render().toString() + } + + private val irLoggerSeverity = when (logLevel) { + PartialLinkageLogLevel.INFO -> IrMessageLogger.Severity.INFO + PartialLinkageLogLevel.WARNING -> IrMessageLogger.Severity.WARNING + PartialLinkageLogLevel.ERROR -> IrMessageLogger.Severity.ERROR + } + + fun log(message: String, location: Location) { + irLogger.report( + severity = irLoggerSeverity, + message = location.render().append(": ").append(message).toString(), + location = null + ) + } +} diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartialLinkageSupportForLinkerImpl.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartialLinkageSupportForLinkerImpl.kt index 3baa6c55089..5f73b9d898a 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartialLinkageSupportForLinkerImpl.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartialLinkageSupportForLinkerImpl.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.linkage.partial.PartialLinkageConfig -import org.jetbrains.kotlin.ir.linkage.partial.PartialLinkageLogLevel +import org.jetbrains.kotlin.ir.linkage.partial.PartialLinkageLogger import org.jetbrains.kotlin.ir.util.IrMessageLogger import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.allUnbound @@ -22,19 +22,18 @@ fun createPartialLinkageSupportForLinker( builtIns: IrBuiltIns, messageLogger: IrMessageLogger ): PartialLinkageSupportForLinker = if (partialLinkageConfig.isEnabled) - PartialLinkageSupportForLinkerImpl(builtIns, allowErrorTypes, partialLinkageConfig.logLevel, messageLogger) + PartialLinkageSupportForLinkerImpl(builtIns, allowErrorTypes, PartialLinkageLogger(messageLogger, partialLinkageConfig.logLevel)) else PartialLinkageSupportForLinker.DISABLED internal class PartialLinkageSupportForLinkerImpl( builtIns: IrBuiltIns, allowErrorTypes: Boolean, - logLevel: PartialLinkageLogLevel, - messageLogger: IrMessageLogger + logger: PartialLinkageLogger ) : PartialLinkageSupportForLinker { private val stubGenerator = MissingDeclarationStubGenerator(builtIns) private val classifierExplorer = ClassifierExplorer(builtIns, stubGenerator, allowErrorTypes) - private val patcher = PartiallyLinkedIrTreePatcher(builtIns, classifierExplorer, stubGenerator, logLevel, messageLogger) + private val patcher = PartiallyLinkedIrTreePatcher(builtIns, classifierExplorer, stubGenerator, logger) override val isEnabled get() = true diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartialLinkageSupportForLoweringsImpl.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartialLinkageSupportForLoweringsImpl.kt index 8be878c4ae6..70b78a97250 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartialLinkageSupportForLoweringsImpl.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartialLinkageSupportForLoweringsImpl.kt @@ -23,14 +23,13 @@ fun createPartialLinkageSupportForLowerings( builtIns: IrBuiltIns, messageLogger: IrMessageLogger ): PartialLinkageSupportForLowerings = if (partialLinkageConfig.isEnabled) - PartialLinkageSupportForLoweringsImpl(builtIns, partialLinkageConfig.logLevel, messageLogger) + PartialLinkageSupportForLoweringsImpl(builtIns, PartialLinkageLogger(messageLogger, partialLinkageConfig.logLevel)) else PartialLinkageSupportForLowerings.DISABLED internal class PartialLinkageSupportForLoweringsImpl( private val builtIns: IrBuiltIns, - logLevel: PartialLinkageLogLevel, - private val messageLogger: IrMessageLogger + private val logger: PartialLinkageLogger ) : PartialLinkageSupportForLowerings { override val isEnabled get() = true @@ -41,12 +40,6 @@ internal class PartialLinkageSupportForLoweringsImpl( var errorMessagesRendered = 0 // Track each rendered error message. private set - private val irLoggerSeverity = when (logLevel) { - PartialLinkageLogLevel.INFO -> IrMessageLogger.Severity.INFO - PartialLinkageLogLevel.WARNING -> IrMessageLogger.Severity.WARNING - PartialLinkageLogLevel.ERROR -> IrMessageLogger.Severity.ERROR - } - override fun throwLinkageError( partialLinkageCase: PartialLinkageCase, element: IrElement, @@ -77,7 +70,7 @@ internal class PartialLinkageSupportForLoweringsImpl( val errorMessage = renderLinkageError(partialLinkageCase) val locationInSourceCode = file.computeLocationForOffset(element.startOffsetOfFirstDenotableIrElement()) - messageLogger.report(irLoggerSeverity, errorMessage, locationInSourceCode) // It's OK. We log it as a warning. + logger.log(errorMessage, locationInSourceCode) return errorMessage } diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartiallyLinkedIrTreePatcher.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartiallyLinkedIrTreePatcher.kt index 0e9c6714c39..48d0921d97d 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartiallyLinkedIrTreePatcher.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartiallyLinkedIrTreePatcher.kt @@ -43,8 +43,7 @@ internal class PartiallyLinkedIrTreePatcher( private val builtIns: IrBuiltIns, private val classifierExplorer: ClassifierExplorer, private val stubGenerator: MissingDeclarationStubGenerator, - logLevel: PartialLinkageLogLevel, - private val messageLogger: IrMessageLogger + logger: PartialLinkageLogger ) { // Avoid revisiting roots that already have been visited. private val visitedModuleFragments = hashSetOf() @@ -56,7 +55,7 @@ internal class PartiallyLinkedIrTreePatcher( private val IrModuleFragment.shouldBeSkipped: Boolean get() = files.isEmpty() || name.asString() == stdlibModule.name // Used only to generate IR expressions that throw linkage errors. - private val supportForLowerings by lazy { PartialLinkageSupportForLoweringsImpl(builtIns, logLevel, messageLogger) } + private val supportForLowerings by lazy { PartialLinkageSupportForLoweringsImpl(builtIns, logger) } fun shouldBeSkipped(declaration: IrDeclaration): Boolean = PLModule.determineModuleFor(declaration).shouldBeSkipped diff --git a/compiler/testData/klibABI/__utils__/__utils__.kt b/compiler/testData/klibABI/__utils__/__utils__.kt index 99ec544d233..6f77de9a7fd 100644 --- a/compiler/testData/klibABI/__utils__/__utils__.kt +++ b/compiler/testData/klibABI/__utils__/__utils__.kt @@ -114,11 +114,15 @@ private sealed interface AbstractFailurePattern : FailurePattern { private sealed class AbstractIrLinkageErrorPattern : AbstractFailurePattern { final override fun validateFailure(t: Throwable) = if (t.isLinkageError) - checkIrLinkageErrorMessage(t.message) // OK, this is IR linkage error. Validate the message. + checkIrLinkageErrorMessage(t.message?.skipLocationPrefix()) // OK, this is IR linkage error. Validate the message. else TestFailedWithException(t) // Unexpected type of exception. abstract fun checkIrLinkageErrorMessage(errorMessage: String?): TestFailureDetails? + + companion object { + private fun String.skipLocationPrefix() = if (startsWith('<')) substringAfter(": ") else this + } } private class GeneralIrLinkageError(private val expectedMessageWithoutHashes: String) : AbstractIrLinkageErrorPattern() { diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/compilation/NativeTestGroupingMessageCollector.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/compilation/NativeTestGroupingMessageCollector.kt index e8de4617a15..375526e76bf 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/compilation/NativeTestGroupingMessageCollector.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/compilation/NativeTestGroupingMessageCollector.kt @@ -68,7 +68,8 @@ internal class NativeTestGroupingMessageCollector( || isUnsafeCompilerArgumentsWarning(message) || isLibraryIncludedMoreThanOnceWarning(message) || isK2Experimental(message) - || isLegacyMMWarning(message) -> { + || isLegacyMMWarning(message) + || isPartialLinkageWarning(message) -> { // These warnings are known and should not be reported as errors. severity } @@ -112,6 +113,8 @@ internal class NativeTestGroupingMessageCollector( // Legacy MM is deprecated and will be removed in 1.9.20. Until that moment we still need to run tests with it. private fun isLegacyMMWarning(message: String): Boolean = message.startsWith(LEGACY_MM_WARNING_PREFIX) + private fun isPartialLinkageWarning(message: String): Boolean = message.matches(PARTIAL_LINKAGE_WARNING_REGEX) + override fun hasErrors() = hasWarningsWithRaisedSeverity || super.hasErrors() companion object { @@ -121,6 +124,8 @@ internal class NativeTestGroupingMessageCollector( private const val K2_NATIVE_EXPERIMENTAL_WARNING_PREFIX = "Language version 2.0 is experimental" private const val LEGACY_MM_WARNING_PREFIX = "Legacy MM is deprecated and will be removed" + private val PARTIAL_LINKAGE_WARNING_REGEX = Regex("^<[^<>]+>( @ (?:(?!: ).)+)?: .*") + private fun parseLanguageFeatureArg(arg: String): String? = substringAfter(arg, "-XXLanguage:-") ?: substringAfter(arg, "-XXLanguage:+") }