JVM IR: do not use JvmDeclarationOrigin in duplicate signatures
Apparently the client code which reports errors only meaningfully uses the `descriptor` field of `JvmDeclarationOrigin` in case of JVM IR.
This commit is contained in:
+2
-1
@@ -78,7 +78,8 @@ abstract class SignatureCollectingClassBuilderFactory(
|
||||
classInternalName,
|
||||
classCreatedFor,
|
||||
signature,
|
||||
elementsAndDescriptors
|
||||
elementsAndDescriptors,
|
||||
elementsAndDescriptors.mapNotNull(JvmDeclarationOrigin::descriptor),
|
||||
))
|
||||
}
|
||||
onClassDone(classCreatedFor, classInternalName, signatures)
|
||||
|
||||
+7
-5
@@ -71,17 +71,17 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
}
|
||||
|
||||
private fun reportConflictingJvmSignatures(data: ConflictingJvmDeclarationsData) {
|
||||
val noOwnImplementations = data.signatureOrigins.all { it.originKind in EXTERNAL_SOURCES_KINDS }
|
||||
val noOwnImplementations = data.signatureOrigins!!.all { it.originKind in EXTERNAL_SOURCES_KINDS }
|
||||
|
||||
val elements = LinkedHashSet<PsiElement>()
|
||||
if (noOwnImplementations) {
|
||||
elements.addIfNotNull(data.classOrigin.element)
|
||||
elements.addIfNotNull(data.classOrigin!!.element)
|
||||
} else {
|
||||
for (origin in data.signatureOrigins) {
|
||||
for (origin in data.signatureOrigins!!) {
|
||||
var element = origin.element
|
||||
|
||||
if (element == null || origin.originKind in EXTERNAL_SOURCES_KINDS) {
|
||||
element = data.classOrigin.element
|
||||
element = data.classOrigin!!.element
|
||||
}
|
||||
|
||||
elements.addIfNotNull(element)
|
||||
@@ -186,7 +186,9 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
}
|
||||
}
|
||||
|
||||
val data = ConflictingJvmDeclarationsData(classInternalName, classOrigin, rawSignature, origins)
|
||||
val data = ConflictingJvmDeclarationsData(
|
||||
classInternalName, classOrigin, rawSignature, origins, origins.mapNotNull(JvmDeclarationOrigin::descriptor),
|
||||
)
|
||||
if (memberElement != null) {
|
||||
return ConflictingDeclarationError.AccidentalOverride(memberElement, data)
|
||||
}
|
||||
|
||||
@@ -120,9 +120,9 @@ class FilteredJvmDiagnostics(val jvmDiagnostics: Diagnostics, val otherDiagnosti
|
||||
}
|
||||
|
||||
private infix fun ConflictingJvmDeclarationsData.higherThan(other: ConflictingJvmDeclarationsData): Boolean {
|
||||
return when (other.classOrigin.originKind) {
|
||||
INTERFACE_DEFAULT_IMPL -> this.classOrigin.originKind != INTERFACE_DEFAULT_IMPL
|
||||
MULTIFILE_CLASS_PART -> this.classOrigin.originKind == MULTIFILE_CLASS
|
||||
return when (other.classOrigin?.originKind) {
|
||||
INTERFACE_DEFAULT_IMPL -> classOrigin?.originKind != INTERFACE_DEFAULT_IMPL
|
||||
MULTIFILE_CLASS_PART -> classOrigin?.originKind == MULTIFILE_CLASS
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
+7
-4
@@ -16,9 +16,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
|
||||
class ConflictingJvmDeclarationsData(
|
||||
val classInternalName: String,
|
||||
val classOrigin: JvmDeclarationOrigin,
|
||||
val signature: RawSignature,
|
||||
val signatureOrigins: Collection<JvmDeclarationOrigin>
|
||||
val classInternalName: String,
|
||||
val classOrigin: JvmDeclarationOrigin?,
|
||||
val signature: RawSignature,
|
||||
val signatureOrigins: Collection<JvmDeclarationOrigin>?,
|
||||
val signatureDescriptors: Collection<DeclarationDescriptor>,
|
||||
)
|
||||
|
||||
+4
-5
@@ -12,8 +12,9 @@ import org.jetbrains.kotlin.resolve.MemberComparator;
|
||||
import org.jetbrains.kotlin.utils.StringsKt;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static kotlin.collections.CollectionsKt.*;
|
||||
import static kotlin.collections.CollectionsKt.map;
|
||||
import static org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING;
|
||||
import static org.jetbrains.kotlin.diagnostics.rendering.Renderers.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.*;
|
||||
@@ -22,10 +23,8 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
|
||||
private static final DiagnosticParameterRenderer<ConflictingJvmDeclarationsData> CONFLICTING_JVM_DECLARATIONS_DATA =
|
||||
(data, context) -> {
|
||||
List<DeclarationDescriptor> renderedDescriptors = sortedWith(
|
||||
mapNotNull(data.getSignatureOrigins(), JvmDeclarationOrigin::getDescriptor),
|
||||
MemberComparator.INSTANCE
|
||||
);
|
||||
List<DeclarationDescriptor> renderedDescriptors =
|
||||
data.getSignatureDescriptors().stream().sorted(MemberComparator.INSTANCE).collect(Collectors.toList());
|
||||
RenderingContext renderingContext = new RenderingContext.Impl(renderedDescriptors);
|
||||
return "The following declarations have the same JVM signature " +
|
||||
"(" + data.getSignature().getName() + data.getSignature().getDesc() + "):\n" +
|
||||
|
||||
+4
-10
@@ -43,20 +43,14 @@ object KtDefaultJvmErrorMessages : BaseDiagnosticRendererFactory() {
|
||||
|
||||
@JvmField
|
||||
val CONFLICTING_JVM_DECLARATIONS_DATA = Renderer<ConflictingJvmDeclarationsData> {
|
||||
val renderedDescriptors: List<DeclarationDescriptor?> =
|
||||
it.signatureOrigins.mapNotNull(
|
||||
JvmDeclarationOrigin::descriptor
|
||||
).sortedWith(MemberComparator.INSTANCE)
|
||||
val renderingContext: RenderingContext =
|
||||
RenderingContext.Impl(renderedDescriptors)
|
||||
val renderedDescriptors = it.signatureDescriptors.sortedWith(MemberComparator.INSTANCE)
|
||||
val renderingContext = RenderingContext.Impl(renderedDescriptors)
|
||||
"""
|
||||
The following declarations have the same JVM signature (${it.signature.name}${it.signature.desc}):
|
||||
|
||||
""".trimIndent() +
|
||||
join(renderedDescriptors.map { descriptor: DeclarationDescriptor? ->
|
||||
" " + Renderers.WITHOUT_MODIFIERS.render(
|
||||
descriptor!!, renderingContext
|
||||
)
|
||||
join(renderedDescriptors.map { descriptor ->
|
||||
" " + Renderers.WITHOUT_MODIFIERS.render(descriptor, renderingContext)
|
||||
}, "\n")
|
||||
}
|
||||
|
||||
|
||||
+2
-4
@@ -111,9 +111,7 @@ class ClassCodegen private constructor(
|
||||
|
||||
private val jvmSignatureClashDetector = JvmSignatureClashDetector(this)
|
||||
|
||||
private val classOrigin = irClass.descriptorOrigin
|
||||
|
||||
private val visitor = state.factory.newVisitor(classOrigin, type, irClass.fileParent.loadSourceFilesInfo()).apply {
|
||||
private val visitor = state.factory.newVisitor(irClass.descriptorOrigin, type, irClass.fileParent.loadSourceFilesInfo()).apply {
|
||||
val signature = typeMapper.mapClassSignature(irClass, type, context.state.classBuilderMode.generateBodies)
|
||||
// Ensure that the backend only produces class names that would be valid in the frontend for JVM.
|
||||
if (context.state.classBuilderMode.generateBodies && signature.hasInvalidName()) {
|
||||
@@ -218,7 +216,7 @@ class ClassCodegen private constructor(
|
||||
generateInnerAndOuterClasses()
|
||||
|
||||
visitor.done(state.generateSmapCopyToAnnotation)
|
||||
jvmSignatureClashDetector.reportErrors(classOrigin)
|
||||
jvmSignatureClashDetector.reportErrors()
|
||||
}
|
||||
|
||||
private fun shouldSkipCodeGenerationAccordingToGenerationFilter(): Boolean {
|
||||
|
||||
+15
-28
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.lower.ANNOTATION_IMPLEMENTATION
|
||||
import org.jetbrains.kotlin.backend.common.psi.PsiSourceManager
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory1
|
||||
@@ -14,7 +13,10 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.toIrBasedDescriptor
|
||||
import org.jetbrains.kotlin.ir.util.file
|
||||
import org.jetbrains.kotlin.ir.util.isFakeOverride
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ConflictingJvmDeclarationsData
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmBackendErrors
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.MemberKind
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.RawSignature
|
||||
import org.jetbrains.kotlin.utils.SmartSet
|
||||
|
||||
class JvmSignatureClashDetector(
|
||||
@@ -66,13 +68,13 @@ class JvmSignatureClashDetector(
|
||||
private fun IrFunction.isSpecialOverride(): Boolean =
|
||||
origin in SPECIAL_BRIDGES_AND_OVERRIDES
|
||||
|
||||
fun reportErrors(classOrigin: JvmDeclarationOrigin) {
|
||||
reportMethodSignatureConflicts(classOrigin)
|
||||
reportPredefinedMethodSignatureConflicts(classOrigin)
|
||||
reportFieldSignatureConflicts(classOrigin)
|
||||
fun reportErrors() {
|
||||
reportMethodSignatureConflicts()
|
||||
reportPredefinedMethodSignatureConflicts()
|
||||
reportFieldSignatureConflicts()
|
||||
}
|
||||
|
||||
private fun reportMethodSignatureConflicts(classOrigin: JvmDeclarationOrigin) {
|
||||
private fun reportMethodSignatureConflicts() {
|
||||
for ((rawSignature, methods) in methodsBySignature) {
|
||||
if (methods.size <= 1) continue
|
||||
|
||||
@@ -80,7 +82,7 @@ class JvmSignatureClashDetector(
|
||||
val specialOverridesCount = methods.count { it.isSpecialOverride() }
|
||||
val realMethodsCount = methods.size - fakeOverridesCount - specialOverridesCount
|
||||
|
||||
val conflictingJvmDeclarationsData = getConflictingJvmDeclarationsData(classOrigin, rawSignature, methods)
|
||||
val conflictingJvmDeclarationsData = getConflictingJvmDeclarationsData(rawSignature, methods)
|
||||
|
||||
when {
|
||||
realMethodsCount == 0 && (fakeOverridesCount > 1 || specialOverridesCount > 1) ->
|
||||
@@ -118,23 +120,22 @@ class JvmSignatureClashDetector(
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportPredefinedMethodSignatureConflicts(classOrigin: JvmDeclarationOrigin) {
|
||||
private fun reportPredefinedMethodSignatureConflicts() {
|
||||
for (predefinedSignature in PREDEFINED_SIGNATURES) {
|
||||
val knownMethods = methodsBySignature[predefinedSignature] ?: continue
|
||||
val methods = knownMethods.filter { !it.isFakeOverride && !it.isSpecialOverride() }
|
||||
if (methods.isEmpty()) continue
|
||||
val conflictingJvmDeclarationsData = ConflictingJvmDeclarationsData(
|
||||
classCodegen.type.internalName, classOrigin, predefinedSignature,
|
||||
methods.map { it.getJvmDeclarationOrigin() } + JvmDeclarationOrigin(JvmDeclarationOriginKind.OTHER, null, null)
|
||||
classCodegen.type.internalName, null, predefinedSignature, null, methods.map(IrFunction::toIrBasedDescriptor),
|
||||
)
|
||||
reportJvmSignatureClash(JvmBackendErrors.ACCIDENTAL_OVERRIDE, methods, conflictingJvmDeclarationsData)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportFieldSignatureConflicts(classOrigin: JvmDeclarationOrigin) {
|
||||
private fun reportFieldSignatureConflicts() {
|
||||
for ((rawSignature, fields) in fieldsBySignature) {
|
||||
if (fields.size <= 1) continue
|
||||
val conflictingJvmDeclarationsData = getConflictingJvmDeclarationsData(classOrigin, rawSignature, fields)
|
||||
val conflictingJvmDeclarationsData = getConflictingJvmDeclarationsData(rawSignature, fields)
|
||||
reportJvmSignatureClash(JvmBackendErrors.CONFLICTING_JVM_DECLARATIONS, fields, conflictingJvmDeclarationsData)
|
||||
}
|
||||
}
|
||||
@@ -152,27 +153,13 @@ class JvmSignatureClashDetector(
|
||||
}
|
||||
|
||||
private fun getConflictingJvmDeclarationsData(
|
||||
classOrigin: JvmDeclarationOrigin,
|
||||
rawSignature: RawSignature,
|
||||
methods: Collection<IrDeclaration>
|
||||
): ConflictingJvmDeclarationsData =
|
||||
ConflictingJvmDeclarationsData(
|
||||
classCodegen.type.internalName,
|
||||
classOrigin,
|
||||
rawSignature,
|
||||
methods.map { it.getJvmDeclarationOrigin() }
|
||||
classCodegen.type.internalName, null, rawSignature, null, methods.map(IrDeclaration::toIrBasedDescriptor),
|
||||
)
|
||||
|
||||
private fun IrDeclaration.getJvmDeclarationOrigin(): JvmDeclarationOrigin {
|
||||
// It looks like 'JvmDeclarationOriginKind' is not really used in error reporting.
|
||||
// However, if needed, we can provide more meaningful information regarding function origin.
|
||||
return JvmDeclarationOrigin(
|
||||
JvmDeclarationOriginKind.OTHER,
|
||||
PsiSourceManager.findPsiElement(this),
|
||||
toIrBasedDescriptor()
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val SPECIAL_BRIDGES_AND_OVERRIDES = setOf(
|
||||
IrDeclarationOrigin.BRIDGE,
|
||||
|
||||
Reference in New Issue
Block a user