mirror of
https://github.com/bevyengine/bevy
synced 2025-01-03 00:38:56 +00:00
bf765e61b5
# Objective - Contributes to #15460 ## Solution - Added `std` feature (enabled by default) ## Testing - CI - `cargo check -p bevy_reflect --no-default-features --target "x86_64-unknown-none"` - UEFI demo application runs with this branch of `bevy_reflect`, allowing `derive(Reflect)` ## Notes - The [`spin`](https://crates.io/crates/spin) crate has been included to provide `RwLock` and `Once` (as an alternative to `OnceLock`) when the `std` feature is not enabled. Another alternative may be more desirable, please provide feedback if you have a strong opinion here! - Certain items (`Box`, `String`, `ToString`) provided by `alloc` have been added to `__macro_exports` as a way to avoid `alloc` vs `std` namespacing. I'm personally quite annoyed that we can't rely on `alloc` as a crate name in `std` environments within macros. I'd love an alternative to my approach here, but I suspect it's the least-bad option. - I would've liked to have an `alloc` feature (for allocation-free `bevy_reflect`), unfortunately, `erased_serde` unconditionally requires access to `Box`. Maybe one day we could design around this, but for now it just means `bevy_reflect` requires `alloc`. --------- Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com> Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
72 lines
2.6 KiB
Rust
72 lines
2.6 KiB
Rust
use crate::derive_data::ReflectMeta;
|
|
use proc_macro2::TokenStream;
|
|
use quote::quote;
|
|
use syn::punctuated::Punctuated;
|
|
use syn::{GenericParam, Token};
|
|
|
|
/// Creates a `TokenStream` for generating an expression that creates a `Generics` instance.
|
|
///
|
|
/// Returns `None` if `Generics` cannot or should not be generated.
|
|
pub(crate) fn generate_generics(meta: &ReflectMeta) -> Option<TokenStream> {
|
|
if !meta.attrs().type_path_attrs().should_auto_derive() {
|
|
// Cannot verify that all generic parameters implement `TypePath`
|
|
return None;
|
|
}
|
|
|
|
let bevy_reflect_path = meta.bevy_reflect_path();
|
|
|
|
let generics = meta
|
|
.type_path()
|
|
.generics()
|
|
.params
|
|
.iter()
|
|
.filter_map(|param| match param {
|
|
GenericParam::Type(ty_param) => {
|
|
let ident = &ty_param.ident;
|
|
let name = ident.to_string();
|
|
let with_default = ty_param
|
|
.default
|
|
.as_ref()
|
|
.map(|default_ty| quote!(.with_default::<#default_ty>()));
|
|
|
|
Some(quote! {
|
|
#bevy_reflect_path::GenericInfo::Type(
|
|
#bevy_reflect_path::TypeParamInfo::new::<#ident>(
|
|
#bevy_reflect_path::__macro_exports::alloc_utils::Cow::Borrowed(#name),
|
|
)
|
|
#with_default
|
|
)
|
|
})
|
|
}
|
|
GenericParam::Const(const_param) => {
|
|
let ty = &const_param.ty;
|
|
let name = const_param.ident.to_string();
|
|
let with_default = const_param.default.as_ref().map(|default| {
|
|
// We add the `as #ty` to ensure that the correct type is inferred.
|
|
quote!(.with_default(#default as #ty))
|
|
});
|
|
|
|
Some(quote! {
|
|
#[allow(
|
|
clippy::unnecessary_cast,
|
|
reason = "reflection requires an explicit type hint for const generics"
|
|
)]
|
|
#bevy_reflect_path::GenericInfo::Const(
|
|
#bevy_reflect_path::ConstParamInfo::new::<#ty>(
|
|
#bevy_reflect_path::__macro_exports::alloc_utils::Cow::Borrowed(#name),
|
|
)
|
|
#with_default
|
|
)
|
|
})
|
|
}
|
|
GenericParam::Lifetime(_) => None,
|
|
})
|
|
.collect::<Punctuated<_, Token![,]>>();
|
|
|
|
if generics.is_empty() {
|
|
// No generics to generate
|
|
return None;
|
|
}
|
|
|
|
Some(quote!(#bevy_reflect_path::Generics::from_iter([ #generics ])))
|
|
}
|