Properly load top-level constant initializers from multifile classes
Before Kotlin 1.3-M2 we didn't write `has_field` flag for constants
inside multifile classes. Now we write and rely on this when
trying to load constant initializers, which is totally fine for
binaries that were compiled with the 1.3-M2 or newer version.
Unfortunately, constant initializers will not be loaded for old binaries.
One way is to avoid relying on this flag, but then we'll get other
problems (e.g. 3345dc81fd).
Therefore, for binaries that were compiled with at least 1.3-M2 version,
we'll rely on the flag, otherwise, we won't.
This commit is contained in:
+15
-7
@@ -221,9 +221,6 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
||||
}
|
||||
|
||||
override fun loadPropertyConstant(container: ProtoContainer, proto: ProtoBuf.Property, expectedType: KotlinType): C? {
|
||||
val signature = getCallableSignature(proto, container.nameResolver, container.typeTable, AnnotatedCallableKind.PROPERTY)
|
||||
?: return null
|
||||
|
||||
val specialCase = getSpecialCaseContainerClass(
|
||||
container,
|
||||
property = true,
|
||||
@@ -233,6 +230,14 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
||||
)
|
||||
val kotlinClass = findClassWithAnnotationsAndInitializers(container, specialCase) ?: return null
|
||||
|
||||
val requireHasFieldFlag = kotlinClass.classHeader.metadataVersion.isAtLeast(
|
||||
DeserializedDescriptorResolver.KOTLIN_1_3_RC_METADATA_VERSION
|
||||
)
|
||||
val signature =
|
||||
getCallableSignature(
|
||||
proto, container.nameResolver, container.typeTable, AnnotatedCallableKind.PROPERTY, requireHasFieldFlag
|
||||
) ?: return null
|
||||
|
||||
val constant = storage(kotlinClass).propertyConstants[signature] ?: return null
|
||||
return if (UnsignedTypes.isUnsignedType(expectedType)) transformToUnsignedConstant(constant) else constant
|
||||
}
|
||||
@@ -352,12 +357,14 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable,
|
||||
field: Boolean = false,
|
||||
synthetic: Boolean = false
|
||||
synthetic: Boolean = false,
|
||||
requireHasFieldFlagForField: Boolean = true
|
||||
): MemberSignature? {
|
||||
val signature = proto.getExtensionOrNull(propertySignature) ?: return null
|
||||
|
||||
if (field) {
|
||||
val fieldSignature = JvmProtoBufUtil.getJvmFieldSignature(proto, nameResolver, typeTable) ?: return null
|
||||
val fieldSignature =
|
||||
JvmProtoBufUtil.getJvmFieldSignature(proto, nameResolver, typeTable, requireHasFieldFlagForField) ?: return null
|
||||
return MemberSignature.fromJvmMemberSignature(fieldSignature)
|
||||
}
|
||||
else if (synthetic && signature.hasSyntheticMethod()) {
|
||||
@@ -371,7 +378,8 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
||||
proto: MessageLite,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable,
|
||||
kind: AnnotatedCallableKind
|
||||
kind: AnnotatedCallableKind,
|
||||
requireHasFieldFlagForField: Boolean = false
|
||||
): MemberSignature? {
|
||||
return when {
|
||||
proto is ProtoBuf.Constructor -> {
|
||||
@@ -388,7 +396,7 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
||||
AnnotatedCallableKind.PROPERTY_SETTER ->
|
||||
if (signature.hasSetter()) MemberSignature.fromMethod(nameResolver, signature.setter) else null
|
||||
AnnotatedCallableKind.PROPERTY ->
|
||||
getPropertySignature(proto, nameResolver, typeTable, true, true)
|
||||
getPropertySignature(proto, nameResolver, typeTable, true, true, requireHasFieldFlagForField)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -127,5 +127,7 @@ class DeserializedDescriptorResolver {
|
||||
private val KOTLIN_1_1_EAP_METADATA_VERSION = JvmMetadataVersion(1, 1, 2)
|
||||
|
||||
private val KOTLIN_1_3_M1_METADATA_VERSION = JvmMetadataVersion(1, 1, 11)
|
||||
|
||||
internal val KOTLIN_1_3_RC_METADATA_VERSION = JvmMetadataVersion(1, 1, 13)
|
||||
}
|
||||
}
|
||||
|
||||
+6
-4
@@ -104,14 +104,16 @@ object JvmProtoBufUtil {
|
||||
fun getJvmFieldSignature(
|
||||
proto: ProtoBuf.Property,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable
|
||||
typeTable: TypeTable,
|
||||
requireHasFieldFlag: Boolean = true
|
||||
): JvmMemberSignature.Field? {
|
||||
val signature = proto.getExtensionOrNull(JvmProtoBuf.propertySignature) ?: return null
|
||||
val field = if (signature.hasField()) signature.field else return null
|
||||
val field = if (signature.hasField()) signature.field else null
|
||||
if (field == null && requireHasFieldFlag) return null
|
||||
|
||||
val name = if (field.hasName()) field.name else proto.name
|
||||
val name = if (field != null && field.hasName()) field.name else proto.name
|
||||
val desc =
|
||||
if (field.hasDesc()) nameResolver.getString(field.desc)
|
||||
if (field != null && field.hasDesc()) nameResolver.getString(field.desc)
|
||||
else mapTypeDefault(proto.returnType(typeTable), nameResolver) ?: return null
|
||||
|
||||
return JvmMemberSignature.Field(nameResolver.getString(name), desc)
|
||||
|
||||
@@ -35,6 +35,9 @@ abstract class BinaryVersion(private vararg val numbers: Int) {
|
||||
else major == ourVersion.major && minor <= ourVersion.minor
|
||||
}
|
||||
|
||||
fun isAtLeast(version: BinaryVersion): Boolean =
|
||||
isAtLeast(version.major, version.minor, version.patch)
|
||||
|
||||
fun isAtLeast(major: Int, minor: Int, patch: Int): Boolean {
|
||||
if (this.major > major) return true
|
||||
if (this.major < major) return false
|
||||
|
||||
Reference in New Issue
Block a user