JVM_IR KT-42020 special IdSignature for some fake override members
This commit is contained in:
@@ -114,6 +114,64 @@ sealed class IdSignature {
|
||||
override fun hashCode(): Int = accessorSignature.hashCode()
|
||||
}
|
||||
|
||||
// KT-42020
|
||||
// This special signature is required to disambiguate fake overrides 'foo(x: T)[T = String]' and 'foo(x: String)' in the code below:
|
||||
//
|
||||
// open class Base<T> {
|
||||
// fun foo(x: T) {}
|
||||
// fun foo(x: String) {}
|
||||
// }
|
||||
//
|
||||
// class Derived : Base<String>()
|
||||
//
|
||||
// (NB similar clash is possible for generic member extension properties as well)
|
||||
//
|
||||
// For each fake override 'foo' we collect non-fake overrides overridden by 'foo'
|
||||
// such that their value parameter types contain type parameters of 'Base',
|
||||
// sorted by the fully-qualified name of the containing class.
|
||||
//
|
||||
// NB this special case of IdSignature is JVM-specific.
|
||||
class SpecialFakeOverrideSignature(
|
||||
val memberSignature: IdSignature,
|
||||
val overriddenSignatures: List<IdSignature>
|
||||
) : IdSignature() {
|
||||
override val isPublic: Boolean
|
||||
get() = memberSignature.isPublic
|
||||
|
||||
override fun topLevelSignature(): IdSignature =
|
||||
memberSignature.topLevelSignature()
|
||||
|
||||
override fun nearestPublicSig(): IdSignature =
|
||||
if (memberSignature.isPublic)
|
||||
this
|
||||
else
|
||||
memberSignature.nearestPublicSig()
|
||||
|
||||
override fun packageFqName(): FqName =
|
||||
memberSignature.packageFqName()
|
||||
|
||||
override fun render(): String =
|
||||
memberSignature.render()
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as SpecialFakeOverrideSignature
|
||||
|
||||
if (memberSignature != other.memberSignature) return false
|
||||
if (overriddenSignatures != other.overriddenSignatures) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = memberSignature.hashCode()
|
||||
result = 31 * result + overriddenSignatures.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
class FileLocalSignature(val container: IdSignature, val id: Long) : IdSignature() {
|
||||
override val isPublic: Boolean get() = false
|
||||
|
||||
|
||||
+20
-8
@@ -14,6 +14,7 @@ abstract class IdSignatureBuilder<D> {
|
||||
protected val classFqnSegments = mutableListOf<String>()
|
||||
protected var hashId: Long? = null
|
||||
protected var hashIdAcc: Long? = null
|
||||
protected var overridden: List<D>? = null
|
||||
protected var mask = 0L
|
||||
|
||||
protected abstract fun accept(d: D)
|
||||
@@ -23,19 +24,30 @@ abstract class IdSignatureBuilder<D> {
|
||||
this.classFqnSegments.clear()
|
||||
this.hashId = null
|
||||
this.mask = 0L
|
||||
this.overridden = null
|
||||
}
|
||||
|
||||
protected fun build(): IdSignature {
|
||||
val packageFqName = packageFqn.asString()
|
||||
val classFqName = classFqnSegments.joinToString(".")
|
||||
return if (hashIdAcc == null) {
|
||||
IdSignature.PublicSignature(packageFqName, classFqName, hashId, mask)
|
||||
} else {
|
||||
val accessorSignature = IdSignature.PublicSignature(packageFqName, classFqName, hashIdAcc, mask)
|
||||
hashIdAcc = null
|
||||
classFqnSegments.run { removeAt(lastIndex) }
|
||||
val propertySignature = build()
|
||||
IdSignature.AccessorSignature(propertySignature, accessorSignature)
|
||||
return when {
|
||||
overridden != null -> {
|
||||
val preserved = overridden!!
|
||||
overridden = null
|
||||
val memberSignature = build()
|
||||
val overriddenSignatures = preserved.map { buildSignature(it) }
|
||||
return IdSignature.SpecialFakeOverrideSignature(memberSignature, overriddenSignatures)
|
||||
}
|
||||
hashIdAcc == null -> {
|
||||
IdSignature.PublicSignature(packageFqName, classFqName, hashId, mask)
|
||||
}
|
||||
else -> {
|
||||
val accessorSignature = IdSignature.PublicSignature(packageFqName, classFqName, hashIdAcc, mask)
|
||||
hashIdAcc = null
|
||||
classFqnSegments.run { removeAt(lastIndex) }
|
||||
val propertySignature = build()
|
||||
IdSignature.AccessorSignature(propertySignature, accessorSignature)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+76
-2
@@ -6,18 +6,92 @@
|
||||
package org.jetbrains.kotlin.backend.jvm.serialization
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.util.KotlinMangler
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaForKotlinOverridePropertyDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeAsSequence
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
class JvmIdSignatureDescriptor(private val mangler: KotlinMangler.DescriptorMangler) : IdSignatureDescriptor(mangler) {
|
||||
|
||||
private class JvmDescriptorBasedSignatureBuilder(mangler: KotlinMangler.DescriptorMangler) : DescriptorBasedSignatureBuilder(mangler) {
|
||||
override fun platformSpecificFunction(descriptor: FunctionDescriptor) {
|
||||
keepTrackOfOverridesForPossiblyClashingFakeOverride(descriptor)
|
||||
}
|
||||
|
||||
override fun platformSpecificProperty(descriptor: PropertyDescriptor) {
|
||||
// See KT-31646
|
||||
setSpecialJavaProperty(descriptor is JavaForKotlinOverridePropertyDescriptor)
|
||||
keepTrackOfOverridesForPossiblyClashingFakeOverride(descriptor)
|
||||
}
|
||||
|
||||
override fun platformSpecificGetter(descriptor: PropertyGetterDescriptor) {
|
||||
keepTrackOfOverridesForPossiblyClashingFakeOverride(descriptor)
|
||||
}
|
||||
|
||||
override fun platformSpecificSetter(descriptor: PropertySetterDescriptor) {
|
||||
keepTrackOfOverridesForPossiblyClashingFakeOverride(descriptor)
|
||||
}
|
||||
|
||||
private fun keepTrackOfOverridesForPossiblyClashingFakeOverride(descriptor: CallableMemberDescriptor) {
|
||||
if (descriptor.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) return
|
||||
val containingClass = descriptor.containingDeclaration as? ClassDescriptor ?: return
|
||||
|
||||
val possiblyClashingMembers = when (descriptor) {
|
||||
is PropertyAccessorDescriptor ->
|
||||
containingClass.unsubstitutedMemberScope
|
||||
.getContributedVariables(descriptor.correspondingProperty.name, NoLookupLocation.FROM_BACKEND)
|
||||
is PropertyDescriptor ->
|
||||
containingClass.unsubstitutedMemberScope
|
||||
.getContributedVariables(descriptor.name, NoLookupLocation.FROM_BACKEND)
|
||||
is FunctionDescriptor ->
|
||||
containingClass.unsubstitutedMemberScope
|
||||
.getContributedFunctions(descriptor.name, NoLookupLocation.FROM_BACKEND)
|
||||
else ->
|
||||
throw AssertionError("Unexpected CallableMemberDescriptor: $descriptor")
|
||||
}
|
||||
if (possiblyClashingMembers.size <= 1) return
|
||||
|
||||
val capturingOverrides = descriptor.overriddenTreeAsSequence(true).filter {
|
||||
it.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && isCapturingTypeParameter(it)
|
||||
}.toList()
|
||||
if (capturingOverrides.isNotEmpty()) {
|
||||
overridden = capturingOverrides.sortedBy {
|
||||
it.containingDeclaration.cast<ClassDescriptor>().fqNameUnsafe.asString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isCapturingTypeParameter(member: CallableMemberDescriptor): Boolean {
|
||||
val containingClasses = collectContainingClasses(member)
|
||||
return member.extensionReceiverParameter?.isCapturingTypeParameter(containingClasses) == true ||
|
||||
member.valueParameters.any { it.isCapturingTypeParameter(containingClasses) }
|
||||
}
|
||||
|
||||
private fun collectContainingClasses(member: CallableMemberDescriptor): Set<ClassDescriptor> {
|
||||
val result = HashSet<ClassDescriptor>()
|
||||
var pointer: DeclarationDescriptor = member
|
||||
while (true) {
|
||||
val containingClass = pointer.containingDeclaration as? ClassDescriptor ?: break
|
||||
result.add(containingClass)
|
||||
if (!containingClass.isInner) break
|
||||
pointer = containingClass
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun ParameterDescriptor.isCapturingTypeParameter(containingClasses: Set<ClassDescriptor>): Boolean =
|
||||
type.containsTypeParametersOf(containingClasses)
|
||||
|
||||
private fun KotlinType.containsTypeParametersOf(containingClasses: Set<ClassDescriptor>): Boolean =
|
||||
contains {
|
||||
val descriptor = it.constructor.declarationDescriptor
|
||||
descriptor is TypeParameterDescriptor && descriptor.containingDeclaration in containingClasses
|
||||
}
|
||||
}
|
||||
|
||||
override fun createSignatureBuilder(): DescriptorBasedSignatureBuilder = JvmDescriptorBasedSignatureBuilder(mangler)
|
||||
|
||||
Reference in New Issue
Block a user