Remove ReflectProperties.lazy, replace with lazy(PUBLICATION)

There's no point in using `ReflectProperties.lazy` over
`lazy(PUBLICATION)`, especially because of the subtle problems the
former can create, such as KT-27585. This is inspired by the fix in
99b38ccb74, although in this case I couldn't come up with an example
that would lead to a runtime exception.
This commit is contained in:
Alexander Udalov
2023-01-24 16:49:56 +01:00
committed by Space Team
parent e0389a0a87
commit 3eb7ac1aac
4 changed files with 35 additions and 61 deletions
@@ -78,7 +78,7 @@ val KClass<*>.defaultType: KType
*/
@SinceKotlin("1.1")
val KClass<*>.declaredMembers: Collection<KCallable<*>>
get() = (this as KClassImpl).data().declaredMembers
get() = (this as KClassImpl).data.value.declaredMembers
/**
* Returns all functions declared in this class, including all non-static methods declared in the class
@@ -93,21 +93,21 @@ val KClass<*>.functions: Collection<KFunction<*>>
*/
@SinceKotlin("1.1")
val KClass<*>.staticFunctions: Collection<KFunction<*>>
get() = (this as KClassImpl).data().allStaticMembers.filterIsInstance<KFunction<*>>()
get() = (this as KClassImpl).data.value.allStaticMembers.filterIsInstance<KFunction<*>>()
/**
* Returns non-extension non-static functions declared in this class and all of its superclasses.
*/
@SinceKotlin("1.1")
val KClass<*>.memberFunctions: Collection<KFunction<*>>
get() = (this as KClassImpl).data().allNonStaticMembers.filter { it.isNotExtension && it is KFunction<*> } as Collection<KFunction<*>>
get() = (this as KClassImpl).data.value.allNonStaticMembers.filter { it.isNotExtension && it is KFunction<*> } as Collection<KFunction<*>>
/**
* Returns extension functions declared in this class and all of its superclasses.
*/
@SinceKotlin("1.1")
val KClass<*>.memberExtensionFunctions: Collection<KFunction<*>>
get() = (this as KClassImpl).data().allNonStaticMembers.filter { it.isExtension && it is KFunction<*> } as Collection<KFunction<*>>
get() = (this as KClassImpl).data.value.allNonStaticMembers.filter { it.isExtension && it is KFunction<*> } as Collection<KFunction<*>>
/**
* Returns all functions declared in this class.
@@ -116,21 +116,21 @@ val KClass<*>.memberExtensionFunctions: Collection<KFunction<*>>
*/
@SinceKotlin("1.1")
val KClass<*>.declaredFunctions: Collection<KFunction<*>>
get() = (this as KClassImpl).data().declaredMembers.filterIsInstance<KFunction<*>>()
get() = (this as KClassImpl).data.value.declaredMembers.filterIsInstance<KFunction<*>>()
/**
* Returns non-extension non-static functions declared in this class.
*/
@SinceKotlin("1.1")
val KClass<*>.declaredMemberFunctions: Collection<KFunction<*>>
get() = (this as KClassImpl).data().declaredNonStaticMembers.filter { it.isNotExtension && it is KFunction<*> } as Collection<KFunction<*>>
get() = (this as KClassImpl).data.value.declaredNonStaticMembers.filter { it.isNotExtension && it is KFunction<*> } as Collection<KFunction<*>>
/**
* Returns extension functions declared in this class.
*/
@SinceKotlin("1.1")
val KClass<*>.declaredMemberExtensionFunctions: Collection<KFunction<*>>
get() = (this as KClassImpl).data().declaredNonStaticMembers.filter { it.isExtension && it is KFunction<*> } as Collection<KFunction<*>>
get() = (this as KClassImpl).data.value.declaredNonStaticMembers.filter { it.isExtension && it is KFunction<*> } as Collection<KFunction<*>>
/**
* Returns static properties declared in this class.
@@ -138,35 +138,35 @@ val KClass<*>.declaredMemberExtensionFunctions: Collection<KFunction<*>>
*/
@SinceKotlin("1.1")
val KClass<*>.staticProperties: Collection<KProperty0<*>>
get() = (this as KClassImpl).data().allStaticMembers.filter { it.isNotExtension && it is KProperty0<*> } as Collection<KProperty0<*>>
get() = (this as KClassImpl).data.value.allStaticMembers.filter { it.isNotExtension && it is KProperty0<*> } as Collection<KProperty0<*>>
/**
* Returns non-extension properties declared in this class and all of its superclasses.
*/
@SinceKotlin("1.1")
val <T : Any> KClass<T>.memberProperties: Collection<KProperty1<T, *>>
get() = (this as KClassImpl<T>).data().allNonStaticMembers.filter { it.isNotExtension && it is KProperty1<*, *> } as Collection<KProperty1<T, *>>
get() = (this as KClassImpl<T>).data.value.allNonStaticMembers.filter { it.isNotExtension && it is KProperty1<*, *> } as Collection<KProperty1<T, *>>
/**
* Returns extension properties declared in this class and all of its superclasses.
*/
@SinceKotlin("1.1")
val <T : Any> KClass<T>.memberExtensionProperties: Collection<KProperty2<T, *, *>>
get() = (this as KClassImpl<T>).data().allNonStaticMembers.filter { it.isExtension && it is KProperty2<*, *, *> } as Collection<KProperty2<T, *, *>>
get() = (this as KClassImpl<T>).data.value.allNonStaticMembers.filter { it.isExtension && it is KProperty2<*, *, *> } as Collection<KProperty2<T, *, *>>
/**
* Returns non-extension properties declared in this class.
*/
@SinceKotlin("1.1")
val <T : Any> KClass<T>.declaredMemberProperties: Collection<KProperty1<T, *>>
get() = (this as KClassImpl<T>).data().declaredNonStaticMembers.filter { it.isNotExtension && it is KProperty1<*, *> } as Collection<KProperty1<T, *>>
get() = (this as KClassImpl<T>).data.value.declaredNonStaticMembers.filter { it.isNotExtension && it is KProperty1<*, *> } as Collection<KProperty1<T, *>>
/**
* Returns extension properties declared in this class.
*/
@SinceKotlin("1.1")
val <T : Any> KClass<T>.declaredMemberExtensionProperties: Collection<KProperty2<T, *, *>>
get() = (this as KClassImpl<T>).data().declaredNonStaticMembers.filter { it.isExtension && it is KProperty2<*, *, *> } as Collection<KProperty2<T, *, *>>
get() = (this as KClassImpl<T>).data.value.declaredNonStaticMembers.filter { it.isExtension && it is KProperty2<*, *, *> } as Collection<KProperty2<T, *, *>>
private val KCallableImpl<*>.isExtension: Boolean
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.deserialization.MemberDeserializer
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
import org.jetbrains.kotlin.utils.compact
import kotlin.LazyThreadSafetyMode.PUBLICATION
import kotlin.jvm.internal.TypeIntrinsics
import kotlin.reflect.*
import kotlin.reflect.jvm.internal.KDeclarationContainerImpl.MemberBelonginess.DECLARED
@@ -47,7 +48,7 @@ internal class KClassImpl<T : Any>(
inner class Data : KDeclarationContainerImpl.Data() {
val descriptor: ClassDescriptor by ReflectProperties.lazySoft {
val classId = classId
val moduleData = data().moduleData
val moduleData = data.value.moduleData
val descriptor =
if (classId.isLocal) moduleData.deserialization.deserializeClass(classId)
@@ -105,7 +106,7 @@ internal class KClassImpl<T : Any>(
}
@Suppress("UNCHECKED_CAST")
val objectInstance: T? by ReflectProperties.lazy {
val objectInstance: T? by lazy(PUBLICATION) {
val descriptor = descriptor
if (descriptor.kind != ClassKind.OBJECT) return@lazy null
@@ -177,11 +178,11 @@ internal class KClassImpl<T : Any>(
by ReflectProperties.lazySoft { allNonStaticMembers + allStaticMembers }
}
val data = ReflectProperties.lazy { Data() }
val data = lazy(PUBLICATION) { Data() }
override val descriptor: ClassDescriptor get() = data().descriptor
override val descriptor: ClassDescriptor get() = data.value.descriptor
override val annotations: List<Annotation> get() = data().annotations
override val annotations: List<Annotation> get() = data.value.annotations
private val classId: ClassId get() = RuntimeTypeMapper.mapJvmClassToKotlinClassId(jClass)
@@ -192,7 +193,7 @@ internal class KClassImpl<T : Any>(
internal val staticScope: MemberScope get() = descriptor.staticScope
override val members: Collection<KCallable<*>> get() = data().allMembers
override val members: Collection<KCallable<*>> get() = data.value.allMembers
override val constructorDescriptors: Collection<ConstructorDescriptor>
get() {
@@ -231,15 +232,15 @@ internal class KClassImpl<T : Any>(
}
}
override val simpleName: String? get() = data().simpleName
override val simpleName: String? get() = data.value.simpleName
override val qualifiedName: String? get() = data().qualifiedName
override val qualifiedName: String? get() = data.value.qualifiedName
override val constructors: Collection<KFunction<T>> get() = data().constructors
override val constructors: Collection<KFunction<T>> get() = data.value.constructors
override val nestedClasses: Collection<KClass<*>> get() = data().nestedClasses
override val nestedClasses: Collection<KClass<*>> get() = data.value.nestedClasses
override val objectInstance: T? get() = data().objectInstance
override val objectInstance: T? get() = data.value.objectInstance
override fun isInstance(value: Any?): Boolean {
// TODO: use Kotlin semantics for mutable/read-only collections once KT-11754 is supported (see TypeIntrinsics)
@@ -249,14 +250,14 @@ internal class KClassImpl<T : Any>(
return (jClass.wrapperByPrimitive ?: jClass).isInstance(value)
}
override val typeParameters: List<KTypeParameter> get() = data().typeParameters
override val typeParameters: List<KTypeParameter> get() = data.value.typeParameters
override val supertypes: List<KType> get() = data().supertypes
override val supertypes: List<KType> get() = data.value.supertypes
/**
* The list of the immediate subclasses if this class is a sealed class, or an empty list otherwise.
*/
override val sealedSubclasses: List<KClass<out T>> get() = data().sealedSubclasses
override val sealedSubclasses: List<KClass<out T>> get() = data.value.sealedSubclasses
override val visibility: KVisibility?
get() = descriptor.visibility.toKVisibility()
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.deserialization.MemberDeserializer
import kotlin.LazyThreadSafetyMode.PUBLICATION
import kotlin.reflect.KCallable
import kotlin.reflect.jvm.internal.KDeclarationContainerImpl.MemberBelonginess.DECLARED
@@ -51,7 +52,7 @@ internal class KPackageImpl(
else MemberScope.Empty
}
val multifileFacade: Class<*>? by ReflectProperties.lazy {
val multifileFacade: Class<*>? by lazy(PUBLICATION) {
val facadeName = kotlinClass?.classHeader?.multifileClassName
// We need to check isNotEmpty because this is the value read from the annotation which cannot be null.
// The default value for 'xs' is empty string, as declared in kotlin.Metadata
@@ -60,7 +61,7 @@ internal class KPackageImpl(
else null
}
val metadata: Triple<JvmNameResolver, ProtoBuf.Package, JvmMetadataVersion>? by ReflectProperties.lazy {
val metadata: Triple<JvmNameResolver, ProtoBuf.Package, JvmMetadataVersion>? by lazy(PUBLICATION) {
kotlinClass?.classHeader?.let { header ->
val data = header.data
val strings = header.strings
@@ -76,13 +77,13 @@ internal class KPackageImpl(
}
}
private val data = ReflectProperties.lazy { Data() }
private val data = lazy(PUBLICATION) { Data() }
override val methodOwner: Class<*> get() = data().multifileFacade ?: jClass
override val methodOwner: Class<*> get() = data.value.multifileFacade ?: jClass
private val scope: MemberScope get() = data().scope
private val scope: MemberScope get() = data.value.scope
override val members: Collection<KCallable<*>> get() = data().members
override val members: Collection<KCallable<*>> get() = data.value.members
override val constructorDescriptors: Collection<ConstructorDescriptor>
get() = emptyList()
@@ -94,7 +95,7 @@ internal class KPackageImpl(
scope.getContributedFunctions(name, NoLookupLocation.FROM_REFLECTION)
override fun getLocalProperty(index: Int): PropertyDescriptor? {
return data().metadata?.let { (nameResolver, packageProto, metadataVersion) ->
return data.value.metadata?.let { (nameResolver, packageProto, metadataVersion) ->
packageProto.getExtensionOrNull(JvmProtoBuf.packageLocalVariable, index)?.let { proto ->
deserializeToDescriptor(
jClass, proto, nameResolver, TypeTable(packageProto.typeTable), metadataVersion,
@@ -44,29 +44,6 @@ public class ReflectProperties {
}
}
// A delegate for a lazy property, whose initializer may be invoked multiple times including simultaneously from different threads
public static class LazyVal<T> extends Val<T> {
private final Function0<T> initializer;
private volatile Object value = null;
public LazyVal(@NotNull Function0<T> initializer) {
this.initializer = initializer;
}
@Override
public T invoke() {
Object cached = value;
if (cached != null) {
return unescape(cached);
}
T result = initializer.invoke();
value = escape(result);
return result;
}
}
// A delegate for a lazy property on a soft reference, whose initializer may be invoked multiple times
// including simultaneously from different threads
public static class LazySoftVal<T> extends Val<T> implements Function0<T> {
@@ -97,11 +74,6 @@ public class ReflectProperties {
}
}
@NotNull
public static <T> LazyVal<T> lazy(@NotNull Function0<T> initializer) {
return new LazyVal<T>(initializer);
}
@NotNull
public static <T> LazySoftVal<T> lazySoft(@Nullable T initialValue, @NotNull Function0<T> initializer) {
return new LazySoftVal<T>(initialValue, initializer);