Don't write type arguments of types replaced with Any to metadata
Anonymous types are not approximated by frontend for private declarations. Class IDs for such types are replaced by StringTable before being written to metadata. JVM string table mangles such types and keeps them generic for reflection. For other purposes the types are replaced with `Any`. Type arguments of the replaced type should be ignored in the latter case. Otherwise decompiled text builder crashes on an attempt to restore `Any` type with non-zero number of type arguments. The code pretending to replace a type with its first supertype was dropped from ApproximatingStringTable for two reasons: - the first type from `getAllSuperClassifiers` is the original type itself which doens't provide a ClassId for anonymous type, so it was a noop - tracking potential type arguments of the first anonymous type's supertype would be a complication with almost no practical value (types in decompiled text would be slightly closer to the real type of a private declaration). ^KT-46393 Fixed
This commit is contained in:
committed by
Space
parent
fefc6f9b53
commit
f5a53c82c5
+3
@@ -29,4 +29,7 @@ class JvmCodegenStringTable @JvmOverloads constructor(
|
||||
ClassId(fqName.parent(), FqName.topLevel(fqName.shortName()), true)
|
||||
}
|
||||
}
|
||||
|
||||
override val isLocalClassIdReplacementKeptGeneric: Boolean
|
||||
get() = true
|
||||
}
|
||||
|
||||
+4
-5
@@ -6,20 +6,19 @@
|
||||
package org.jetbrains.kotlin.serialization
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
|
||||
|
||||
class ApproximatingStringTable : StringTableImpl() {
|
||||
override fun getLocalClassIdReplacement(descriptor: ClassifierDescriptorWithTypeParameters): ClassId? {
|
||||
return if (DescriptorUtils.isLocal(descriptor)) {
|
||||
descriptor.getAllSuperClassifiers().firstOrNull()?.classId
|
||||
?: ClassId.topLevel(StandardNames.FqNames.any.toSafe())
|
||||
ClassId.topLevel(StandardNames.FqNames.any.toSafe())
|
||||
} else {
|
||||
super.getLocalClassIdReplacement(descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
override val isLocalClassIdReplacementKeptGeneric: Boolean
|
||||
get() = false
|
||||
}
|
||||
|
||||
+8
@@ -30,6 +30,14 @@ interface DescriptorAwareStringTable : StringTable {
|
||||
|
||||
fun getLocalClassIdReplacement(descriptor: ClassifierDescriptorWithTypeParameters): ClassId? = null
|
||||
|
||||
/**
|
||||
* true if this [StringTable] replaces absent [ClassId] of a local class descriptor with a semantic equivalent that
|
||||
* still expects original type arguments when used in a type
|
||||
* false otherwise
|
||||
*/
|
||||
val isLocalClassIdReplacementKeptGeneric: Boolean
|
||||
get() = false
|
||||
|
||||
private fun renderDescriptor(descriptor: ClassifierDescriptorWithTypeParameters): String =
|
||||
DescriptorRenderer.COMPACT.render(descriptor) + " defined in " +
|
||||
DescriptorRenderer.FQ_NAMES_IN_TYPES.render(descriptor.containingDeclaration)
|
||||
|
||||
+6
-2
@@ -671,13 +671,17 @@ class DescriptorSerializer private constructor(
|
||||
private fun fillFromPossiblyInnerType(builder: ProtoBuf.Type.Builder, type: PossiblyInnerType) {
|
||||
val classifierDescriptor = type.classifierDescriptor
|
||||
val classifierId = getClassifierId(classifierDescriptor)
|
||||
|
||||
when (classifierDescriptor) {
|
||||
is ClassDescriptor -> builder.className = classifierId
|
||||
is TypeAliasDescriptor -> builder.typeAliasName = classifierId
|
||||
}
|
||||
|
||||
for (projection in type.arguments) {
|
||||
builder.addArgument(typeArgument(projection))
|
||||
// Shouldn't write type parameters of a generic local anonymous type if it was replaced with Any
|
||||
if (stringTable.isLocalClassIdReplacementKeptGeneric || !DescriptorUtils.isLocal(classifierDescriptor)) {
|
||||
for (projection in type.arguments) {
|
||||
builder.addArgument(typeArgument(projection))
|
||||
}
|
||||
}
|
||||
|
||||
if (type.outerType != null) {
|
||||
|
||||
@@ -89,4 +89,7 @@ open class StringTableImpl : DescriptorAwareStringTable {
|
||||
|
||||
return Pair(strings.build(), qualifiedNames.build())
|
||||
}
|
||||
|
||||
override val isLocalClassIdReplacementKeptGeneric: Boolean
|
||||
get() = false
|
||||
}
|
||||
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
// TODO: See KT-13618
|
||||
// IGNORE_BACKEND: JS
|
||||
Reference in New Issue
Block a user