deny(missing_docs) for bevy_reflect (#19481)

## Objective

Deny missing docs in bevy_reflect, towards
https://github.com/bevyengine/bevy/issues/3492.

## Solution

Add the missing docs!

## Testing

N/A
This commit is contained in:
theotherphil 2025-06-16 22:26:24 +01:00 committed by GitHub
parent 6db71367d4
commit 3b25b38bdc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 229 additions and 9 deletions

View File

@ -167,6 +167,7 @@ pub struct DynamicArray {
}
impl DynamicArray {
/// Creates a new [`DynamicArray`].
#[inline]
pub fn new(values: Box<[Box<dyn PartialReflect>]>) -> Self {
Self {

View File

@ -1,3 +1,5 @@
//! Types and functions for creating, manipulating and querying [`CustomAttributes`].
use crate::Reflect;
use alloc::boxed::Box;
use bevy_utils::TypeIdMap;
@ -98,16 +100,19 @@ struct CustomAttribute {
}
impl CustomAttribute {
/// Creates a new [`CustomAttribute`] containing `value`.
pub fn new<T: Reflect>(value: T) -> Self {
Self {
value: Box::new(value),
}
}
/// Returns a reference to the attribute's value if it is of type `T`, or [`None`] if not.
pub fn value<T: Reflect>(&self) -> Option<&T> {
self.value.downcast_ref()
}
/// Returns a reference to the attribute's value as a [`Reflect`] trait object.
pub fn reflect_value(&self) -> &dyn Reflect {
&*self.value
}

View File

@ -13,9 +13,12 @@ use derive_more::derive::From;
/// A dynamic representation of an enum variant.
#[derive(Debug, Default, From)]
pub enum DynamicVariant {
/// A unit variant.
#[default]
Unit,
/// A tuple variant.
Tuple(DynamicTuple),
/// A struct variant.
Struct(DynamicStruct),
}

View File

@ -263,6 +263,7 @@ pub struct VariantFieldIter<'a> {
}
impl<'a> VariantFieldIter<'a> {
/// Creates a new [`VariantFieldIter`].
pub fn new(container: &'a dyn Enum) -> Self {
Self {
container,
@ -295,12 +296,16 @@ impl<'a> Iterator for VariantFieldIter<'a> {
impl<'a> ExactSizeIterator for VariantFieldIter<'a> {}
/// A field in the current enum variant.
pub enum VariantField<'a> {
/// The name and value of a field in a struct variant.
Struct(&'a str, &'a dyn PartialReflect),
/// The value of a field in a tuple variant.
Tuple(&'a dyn PartialReflect),
}
impl<'a> VariantField<'a> {
/// Returns the name of a struct variant field, or [`None`] for a tuple variant field.
pub fn name(&self) -> Option<&'a str> {
if let Self::Struct(name, ..) = self {
Some(*name)
@ -309,6 +314,7 @@ impl<'a> VariantField<'a> {
}
}
/// Gets a reference to the value of this field.
pub fn value(&self) -> &'a dyn PartialReflect {
match *self {
Self::Struct(_, value) | Self::Tuple(value) => value,

View File

@ -47,7 +47,9 @@ pub enum VariantInfoError {
/// [type]: VariantType
#[error("variant type mismatch: expected {expected:?}, received {received:?}")]
TypeMismatch {
/// Expected variant type.
expected: VariantType,
/// Received variant type.
received: VariantType,
},
}
@ -84,6 +86,7 @@ pub enum VariantInfo {
}
impl VariantInfo {
/// The name of the enum variant.
pub fn name(&self) -> &'static str {
match self {
Self::Struct(info) => info.name(),

View File

@ -11,14 +11,20 @@ pub enum ReflectCloneError {
///
/// [`PartialReflect::reflect_clone`]: crate::PartialReflect::reflect_clone
#[error("`PartialReflect::reflect_clone` not implemented for `{type_path}`")]
NotImplemented { type_path: Cow<'static, str> },
NotImplemented {
/// The fully qualified path of the type that [`PartialReflect::reflect_clone`](crate::PartialReflect::reflect_clone) is not implemented for.
type_path: Cow<'static, str>,
},
/// The type cannot be cloned via [`PartialReflect::reflect_clone`].
///
/// This type should be returned when a type is intentionally opting out of reflection cloning.
///
/// [`PartialReflect::reflect_clone`]: crate::PartialReflect::reflect_clone
#[error("`{type_path}` cannot be made cloneable for `PartialReflect::reflect_clone`")]
NotCloneable { type_path: Cow<'static, str> },
NotCloneable {
/// The fully qualified path of the type that cannot be cloned via [`PartialReflect::reflect_clone`](crate::PartialReflect::reflect_clone).
type_path: Cow<'static, str>,
},
/// The field cannot be cloned via [`PartialReflect::reflect_clone`].
///
/// When [deriving `Reflect`], this usually means that a field marked with `#[reflect(ignore)]`
@ -33,8 +39,11 @@ pub enum ReflectCloneError {
full_path(.field, .variant.as_deref(), .container_type_path)
)]
FieldNotCloneable {
/// Struct field or enum variant field which cannot be cloned.
field: FieldId,
/// Variant this field is part of if the container is an enum, otherwise [`None`].
variant: Option<Cow<'static, str>>,
/// Fully qualified path of the type containing this field.
container_type_path: Cow<'static, str>,
},
/// Could not downcast to the expected type.
@ -44,7 +53,9 @@ pub enum ReflectCloneError {
/// [`Reflect`]: crate::Reflect
#[error("expected downcast to `{expected}`, but received `{received}`")]
FailedDowncast {
/// The fully qualified path of the type that was expected.
expected: Cow<'static, str>,
/// The fully qualified path of the type that was received.
received: Cow<'static, str>,
},
}

View File

@ -82,6 +82,7 @@ pub struct UnnamedField {
}
impl UnnamedField {
/// Create a new [`UnnamedField`].
pub fn new<T: PartialReflect + MaybeTyped + TypePath>(index: usize) -> Self {
Self {
index,
@ -135,7 +136,9 @@ impl UnnamedField {
/// A representation of a field's accessor.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum FieldId {
/// Access a field by name.
Named(Cow<'static, str>),
/// Access a field by index.
Unnamed(usize),
}

View File

@ -196,8 +196,11 @@ impl<'a> Arg<'a> {
/// [`DynamicFunctionMut`]: crate::func::DynamicFunctionMut
#[derive(Debug)]
pub enum ArgValue<'a> {
/// An owned argument.
Owned(Box<dyn PartialReflect>),
/// An immutable reference argument.
Ref(&'a dyn PartialReflect),
/// A mutable reference argument.
Mut(&'a mut dyn PartialReflect),
}

View File

@ -12,15 +12,21 @@ pub enum ArgError {
/// The argument is not the expected type.
#[error("expected `{expected}` but received `{received}` (@ argument index {index})")]
UnexpectedType {
/// Argument index.
index: usize,
/// Expected argument type path.
expected: Cow<'static, str>,
/// Received argument type path.
received: Cow<'static, str>,
},
/// The argument has the wrong ownership.
#[error("expected {expected} value but received {received} value (@ argument index {index})")]
InvalidOwnership {
/// Argument index.
index: usize,
/// Expected ownership.
expected: Ownership,
/// Received ownership.
received: Ownership,
},
/// Occurs when attempting to access an argument from an empty [`ArgList`].

View File

@ -18,11 +18,18 @@ pub enum FunctionError {
ArgError(#[from] ArgError),
/// The number of arguments provided does not match the expected number.
#[error("received {received} arguments but expected one of {expected:?}")]
ArgCountMismatch { expected: ArgCount, received: usize },
ArgCountMismatch {
/// Expected argument count. [`ArgCount`] for overloaded functions will contain multiple possible counts.
expected: ArgCount,
/// Number of arguments received.
received: usize,
},
/// No overload was found for the given set of arguments.
#[error("no overload found for arguments with signature `{received:?}`, expected one of `{expected:?}`")]
NoOverload {
/// The set of available argument signatures.
expected: HashSet<ArgumentSignature>,
/// The received argument signature.
received: ArgumentSignature,
},
}
@ -47,6 +54,9 @@ pub enum FunctionOverloadError {
/// An error that occurs when attempting to add a function overload with a duplicate signature.
#[error("could not add function overload: duplicate found for signature `{0:?}`")]
DuplicateSignature(ArgumentSignature),
/// An attempt was made to add an overload with more than [`ArgCount::MAX_COUNT`] arguments.
///
/// [`ArgCount::MAX_COUNT`]: crate::func::args::ArgCount
#[error(
"argument signature `{:?}` has too many arguments (max {})",
0,

View File

@ -235,6 +235,12 @@ impl<const N: usize> TryFrom<[SignatureInfo; N]> for FunctionInfo {
}
}
/// Type information for the signature of a [`DynamicFunction`] or [`DynamicFunctionMut`].
///
/// Every [`FunctionInfo`] contains one or more [`SignatureInfo`]s.
///
/// [`DynamicFunction`]: crate::func::DynamicFunction
/// [`DynamicFunctionMut`]: crate::func::DynamicFunctionMut
#[derive(Debug, Clone)]
pub struct SignatureInfo {
name: Option<Cow<'static, str>>,

View File

@ -42,7 +42,7 @@
//!
//! A "function" is a callable that does not capture its environment.
//! These are typically defined with the `fn` keyword, which are referred to as _named_ functions.
//! But they are also _anonymous_ functions, which are unnamed and defined with anonymous function syntax.
//! But there are also _anonymous_ functions, which are unnamed and defined with anonymous function syntax.
//!
//! ```rust
//! // This is a named function:

View File

@ -336,6 +336,7 @@ impl Debug for FunctionRegistry {
/// A synchronized wrapper around a [`FunctionRegistry`].
#[derive(Clone, Default, Debug)]
pub struct FunctionRegistryArc {
/// The wrapped [`FunctionRegistry`].
pub internal: Arc<RwLock<FunctionRegistry>>,
}

View File

@ -134,7 +134,9 @@ macro_rules! impl_reflect_kind_conversions {
#[derive(Debug, Error)]
#[error("kind mismatch: expected {expected:?}, received {received:?}")]
pub struct ReflectKindMismatchError {
/// Expected kind.
pub expected: ReflectKind,
/// Received kind.
pub received: ReflectKind,
}
@ -176,16 +178,46 @@ macro_rules! impl_cast_method {
///
/// ["kinds"]: ReflectKind
pub enum ReflectRef<'a> {
/// An immutable reference to a [struct-like] type.
///
/// [struct-like]: Struct
Struct(&'a dyn Struct),
/// An immutable reference to a [tuple-struct-like] type.
///
/// [tuple-struct-like]: TupleStruct
TupleStruct(&'a dyn TupleStruct),
/// An immutable reference to a [tuple-like] type.
///
/// [tuple-like]: Tuple
Tuple(&'a dyn Tuple),
/// An immutable reference to a [list-like] type.
///
/// [list-like]: List
List(&'a dyn List),
/// An immutable reference to an [array-like] type.
///
/// [array-like]: Array
Array(&'a dyn Array),
/// An immutable reference to a [map-like] type.
///
/// [map-like]: Map
Map(&'a dyn Map),
/// An immutable reference to a [set-like] type.
///
/// [set-like]: Set
Set(&'a dyn Set),
/// An immutable reference to an [enum-like] type.
///
/// [enum-like]: Enum
Enum(&'a dyn Enum),
/// An immutable reference to a [function-like] type.
///
/// [function-like]: Function
#[cfg(feature = "functions")]
Function(&'a dyn Function),
/// An immutable refeence to an [opaque] type.
///
/// [opaque]: ReflectKind::Opaque
Opaque(&'a dyn PartialReflect),
}
impl_reflect_kind_conversions!(ReflectRef<'_>);
@ -211,16 +243,46 @@ impl<'a> ReflectRef<'a> {
///
/// ["kinds"]: ReflectKind
pub enum ReflectMut<'a> {
/// A mutable reference to a [struct-like] type.
///
/// [struct-like]: Struct
Struct(&'a mut dyn Struct),
/// A mutable reference to a [tuple-struct-like] type.
///
/// [tuple-struct-like]: TupleStruct
TupleStruct(&'a mut dyn TupleStruct),
/// A mutable reference to a [tuple-like] type.
///
/// [tuple-like]: Tuple
Tuple(&'a mut dyn Tuple),
/// A mutable reference to a [list-like] type.
///
/// [list-like]: List
List(&'a mut dyn List),
/// A mutable reference to an [array-like] type.
///
/// [array-like]: Array
Array(&'a mut dyn Array),
/// A mutable reference to a [map-like] type.
///
/// [map-like]: Map
Map(&'a mut dyn Map),
/// A mutable reference to a [set-like] type.
///
/// [set-like]: Set
Set(&'a mut dyn Set),
/// A mutable reference to an [enum-like] type.
///
/// [enum-like]: Enum
Enum(&'a mut dyn Enum),
#[cfg(feature = "functions")]
/// A mutable reference to a [function-like] type.
///
/// [function-like]: Function
Function(&'a mut dyn Function),
/// A mutable refeence to an [opaque] type.
///
/// [opaque]: ReflectKind::Opaque
Opaque(&'a mut dyn PartialReflect),
}
impl_reflect_kind_conversions!(ReflectMut<'_>);
@ -246,16 +308,46 @@ impl<'a> ReflectMut<'a> {
///
/// ["kinds"]: ReflectKind
pub enum ReflectOwned {
/// An owned [struct-like] type.
///
/// [struct-like]: Struct
Struct(Box<dyn Struct>),
/// An owned [tuple-struct-like] type.
///
/// [tuple-struct-like]: TupleStruct
TupleStruct(Box<dyn TupleStruct>),
/// An owned [tuple-like] type.
///
/// [tuple-like]: Tuple
Tuple(Box<dyn Tuple>),
/// An owned [list-like] type.
///
/// [list-like]: List
List(Box<dyn List>),
/// An owned [array-like] type.
///
/// [array-like]: Array
Array(Box<dyn Array>),
/// An owned [map-like] type.
///
/// [map-like]: Map
Map(Box<dyn Map>),
/// An owned [set-like] type.
///
/// [set-like]: Set
Set(Box<dyn Set>),
/// An owned [enum-like] type.
///
/// [enum-like]: Enum
Enum(Box<dyn Enum>),
/// An owned [function-like] type.
///
/// [function-like]: Function
#[cfg(feature = "functions")]
Function(Box<dyn Function>),
/// An owned [opaque] type.
///
/// [opaque]: ReflectKind::Opaque
Opaque(Box<dyn PartialReflect>),
}
impl_reflect_kind_conversions!(ReflectOwned);

View File

@ -1,4 +1,3 @@
#![expect(missing_docs, reason = "Not all docs are written yet, see #3492.")]
#![cfg_attr(
any(docsrs, docsrs_dep),
expect(

View File

@ -192,6 +192,8 @@ impl MapInfo {
impl_generic_info_methods!(generics);
}
/// Used to produce an error message when an attempt is made to hash
/// a [`PartialReflect`] value that does not support hashing.
#[macro_export]
macro_rules! hash_error {
( $key:expr ) => {{

View File

@ -21,32 +21,47 @@ pub enum ApplyError {
#[error("attempted to apply `{from_kind}` to `{to_kind}`")]
/// Attempted to apply the wrong [kind](ReflectKind) to a type, e.g. a struct to an enum.
MismatchedKinds {
/// Kind of the value we attempted to apply.
from_kind: ReflectKind,
/// Kind of the type we attempted to apply the value to.
to_kind: ReflectKind,
},
#[error("enum variant `{variant_name}` doesn't have a field named `{field_name}`")]
/// Enum variant that we tried to apply to was missing a field.
MissingEnumField {
/// Name of the enum variant.
variant_name: Box<str>,
/// Name of the missing field.
field_name: Box<str>,
},
#[error("`{from_type}` is not `{to_type}`")]
/// Tried to apply incompatible types.
MismatchedTypes {
/// Type of the value we attempted to apply.
from_type: Box<str>,
/// Type we attempted to apply the value to.
to_type: Box<str>,
},
#[error("attempted to apply type with {from_size} size to a type with {to_size} size")]
/// Attempted to apply to types with mismatched sizes, e.g. a [u8; 4] to [u8; 3].
DifferentSize { from_size: usize, to_size: usize },
/// Attempted to apply an [array-like] type to another of different size, e.g. a [u8; 4] to [u8; 3].
///
/// [array-like]: crate::Array
DifferentSize {
/// Size of the value we attempted to apply, in elements.
from_size: usize,
/// Size of the type we attempted to apply the value to, in elements.
to_size: usize,
},
#[error("variant with name `{variant_name}` does not exist on enum `{enum_name}`")]
/// The enum we tried to apply to didn't contain a variant with the give name.
UnknownVariant {
/// Name of the enum.
enum_name: Box<str>,
/// Name of the missing variant.
variant_name: Box<str>,
},
}

View File

@ -42,6 +42,9 @@ use serde::Deserializer;
/// [`ReflectDeserializer`]: crate::serde::ReflectDeserializer
/// [via the registry]: TypeRegistry::register_type_data
pub trait DeserializeWithRegistry<'de>: Sized {
/// Deserialize this value using the given [Deserializer] and [`TypeRegistry`].
///
/// [`Deserializer`]: ::serde::Deserializer
fn deserialize<D>(deserializer: D, registry: &TypeRegistry) -> Result<Self, D::Error>
where
D: Deserializer<'de>;

View File

@ -15,6 +15,7 @@ pub struct TypeRegistrationDeserializer<'a> {
}
impl<'a> TypeRegistrationDeserializer<'a> {
/// Creates a new [`TypeRegistrationDeserializer`].
pub fn new(registry: &'a TypeRegistry) -> Self {
Self { registry }
}

View File

@ -1,3 +1,5 @@
//! Serde integration for reflected types.
mod de;
mod ser;
mod type_data;

View File

@ -3,7 +3,9 @@ use core::ops::Deref;
/// A type-erased serializable value.
pub enum Serializable<'a> {
/// An owned serializable value.
Owned(Box<dyn erased_serde::Serialize + 'a>),
/// An immutable reference to a serializable value.
Borrowed(&'a dyn erased_serde::Serialize),
}

View File

@ -40,6 +40,9 @@ use serde::{Serialize, Serializer};
/// [`ReflectSerializer`]: crate::serde::ReflectSerializer
/// [via the registry]: TypeRegistry::register_type_data
pub trait SerializeWithRegistry {
/// Serialize this value using the given [Serializer] and [`TypeRegistry`].
///
/// [`Serializer`]: ::serde::Serializer
fn serialize<S>(&self, serializer: S, registry: &TypeRegistry) -> Result<S::Ok, S::Error>
where
S: Serializer;

View File

@ -1,3 +1,5 @@
//! Module containing the [`ReflectDefault`] type.
use crate::{FromType, Reflect};
use alloc::boxed::Box;
@ -10,6 +12,7 @@ pub struct ReflectDefault {
}
impl ReflectDefault {
/// Returns the default value for a type.
pub fn default(&self) -> Box<dyn Reflect> {
(self.default)()
}

View File

@ -71,6 +71,7 @@ pub trait Struct: PartialReflect {
/// Returns an iterator over the values of the reflectable fields for this struct.
fn iter_fields(&self) -> FieldIter;
/// Creates a new [`DynamicStruct`] from this struct.
fn to_dynamic_struct(&self) -> DynamicStruct {
let mut dynamic_struct = DynamicStruct::default();
dynamic_struct.set_represented_type(self.get_represented_type_info());
@ -192,6 +193,7 @@ pub struct FieldIter<'a> {
}
impl<'a> FieldIter<'a> {
/// Creates a new [`FieldIter`].
pub fn new(value: &'a dyn Struct) -> Self {
FieldIter {
struct_val: value,

View File

@ -76,6 +76,7 @@ pub struct TupleFieldIter<'a> {
}
impl<'a> TupleFieldIter<'a> {
/// Creates a new [`TupleFieldIter`].
pub fn new(value: &'a dyn Tuple) -> Self {
TupleFieldIter {
tuple: value,

View File

@ -146,6 +146,7 @@ pub struct TupleStructFieldIter<'a> {
}
impl<'a> TupleStructFieldIter<'a> {
/// Creates a new [`TupleStructFieldIter`].
pub fn new(value: &'a dyn TupleStruct) -> Self {
TupleStructFieldIter {
tuple_struct: value,

View File

@ -169,7 +169,9 @@ pub enum TypeInfoError {
/// [kind]: ReflectKind
#[error("kind mismatch: expected {expected:?}, received {received:?}")]
KindMismatch {
/// Expected kind.
expected: ReflectKind,
/// Received kind.
received: ReflectKind,
},
}
@ -183,7 +185,7 @@ pub enum TypeInfoError {
/// 3. [`PartialReflect::get_represented_type_info`]
/// 4. [`TypeRegistry::get_type_info`]
///
/// Each return a static reference to [`TypeInfo`], but they all have their own use cases.
/// Each returns a static reference to [`TypeInfo`], but they all have their own use cases.
/// For example, if you know the type at compile time, [`Typed::type_info`] is probably
/// the simplest. If you have a `dyn Reflect` you can use [`DynamicTyped::reflect_type_info`].
/// If all you have is a `dyn PartialReflect`, you'll probably want [`PartialReflect::get_represented_type_info`].
@ -199,14 +201,40 @@ pub enum TypeInfoError {
/// [type path]: TypePath::type_path
#[derive(Debug, Clone)]
pub enum TypeInfo {
/// Type information for a [struct-like] type.
///
/// [struct-like]: crate::Struct
Struct(StructInfo),
/// Type information for a [tuple-struct-like] type.
///
/// [tuple-struct-like]: crate::TupleStruct
TupleStruct(TupleStructInfo),
/// Type information for a [tuple-like] type.
///
/// [tuple-like]: crate::Tuple
Tuple(TupleInfo),
/// Type information for a [list-like] type.
///
/// [list-like]: crate::List
List(ListInfo),
/// Type information for an [array-like] type.
///
/// [array-like]: crate::Array
Array(ArrayInfo),
/// Type information for a [map-like] type.
///
/// [map-like]: crate::Map
Map(MapInfo),
/// Type information for a [set-like] type.
///
/// [set-like]: crate::Set
Set(SetInfo),
/// Type information for an [enum-like] type.
///
/// [enum-like]: crate::Enum
Enum(EnumInfo),
/// Type information for an opaque type - see the [`OpaqueInfo`] docs for
/// a discussion of opaque types.
Opaque(OpaqueInfo),
}
@ -557,6 +585,7 @@ pub struct OpaqueInfo {
}
impl OpaqueInfo {
/// Creates a new [`OpaqueInfo`].
pub fn new<T: Reflect + TypePath + ?Sized>() -> Self {
Self {
ty: Type::of::<T>(),

View File

@ -38,6 +38,7 @@ pub struct TypeRegistry {
/// A synchronized wrapper around a [`TypeRegistry`].
#[derive(Clone, Default)]
pub struct TypeRegistryArc {
/// The wrapped [`TypeRegistry`].
pub internal: Arc<RwLock<TypeRegistry>>,
}
@ -313,6 +314,7 @@ impl TypeRegistry {
data.insert(D::from_type());
}
/// Whether the type with given [`TypeId`] has been registered in this registry.
pub fn contains(&self, type_id: TypeId) -> bool {
self.registrations.contains_key(&type_id)
}
@ -684,6 +686,7 @@ impl Clone for TypeRegistration {
///
/// [crate-level documentation]: crate
pub trait TypeData: Downcast + Send + Sync {
/// Creates a type-erased clone of this value.
fn clone_type_data(&self) -> Box<dyn TypeData>;
}
impl_downcast!(TypeData);
@ -702,6 +705,7 @@ where
/// This is used by the `#[derive(Reflect)]` macro to generate an implementation
/// of [`TypeData`] to pass to [`TypeRegistration::insert`].
pub trait FromType<T> {
/// Creates an instance of `Self` for type `T`.
fn from_type() -> Self;
}
@ -746,6 +750,8 @@ impl ReflectSerialize {
/// [`FromType::from_type`].
#[derive(Clone)]
pub struct ReflectDeserialize {
/// Function used by [`ReflectDeserialize::deserialize`] to
/// perform deserialization.
pub func: fn(
deserializer: &mut dyn erased_serde::Deserializer,
) -> Result<Box<dyn Reflect>, erased_serde::Error>,

View File

@ -16,6 +16,7 @@ use core::{
///
/// [`Non`]: NonGenericTypeCell
pub trait TypedProperty: sealed::Sealed {
/// The type of the value stored in [`GenericTypeCell`].
type Stored: 'static;
}
@ -201,7 +202,7 @@ impl<T: TypedProperty> Default for NonGenericTypeCell<T> {
/// static CELL: GenericTypePathCell = GenericTypePathCell::new();
/// CELL.get_or_insert::<Self, _>(|| format!("my_crate::foo::Foo<{}>", T::type_path()))
/// }
///
///
/// fn short_type_path() -> &'static str {
/// static CELL: GenericTypePathCell = GenericTypePathCell::new();
/// CELL.get_or_insert::<Self, _>(|| format!("Foo<{}>", T::short_type_path()))