[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
@@ -9,6 +9,7 @@ import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.addToStdlib.joinToWithBuffer
import java.io.PrintWriter
import java.io.StringWriter
@@ -63,4 +64,27 @@ object CommonRenderers {
}
}
}
@JvmStatic
fun <Declaration, Data> renderConflictingSignatureData(
signatureKind: String,
sortUsing: Comparator<Declaration>,
declarationRenderer: DiagnosticParameterRenderer<Declaration>,
renderSignature: StringBuilder.(Data) -> Unit,
declarations: (Data) -> Collection<Declaration>,
) = Renderer<Data> { data ->
val sortedDeclarations = declarations(data).sortedWith(sortUsing)
val renderingContext = RenderingContext.Impl(sortedDeclarations)
buildString {
append("The following declarations have the same ")
append(signatureKind)
append(" signature (")
renderSignature(data)
appendLine("):")
sortedDeclarations.joinToWithBuffer(this, separator = "\n") { descriptor ->
append(" ")
append(declarationRenderer.render(descriptor, renderingContext))
}
}
}
}