
# Objective `#[derive(Reflect)]` derives `Typed` impls whose `type_info` methods contain useless calls to `with_custom_attributes` and `with_docs`, e.g.: ``` ::bevy::reflect::NamedField:🆕:<f32>("x") .with_custom_attributes( ::bevy::reflect::attributes::CustomAttributes::default() ) .with_docs(::core::option::Option::None), ``` This hurts compile times and makes the `cargo expand` output harder to read. It might also hurt runtime speed, depending on whether the compiler can optimize away the no-op methods. Avoiding this will help with #19873. ## Solution Check if the attributes/docs are empty before appending the method calls. ## Testing I used `cargo expand` to confirm the useless calls are no longer produced. `-Zmacro-stats` outputs tells me this reduces the size of the `Reflect` impls produced for `bevy_ui` from 1_544_696 bytes to 1_511_214 bytes, a 2.2% drop. Only a small improvement, but it's a start.
47 lines
1.2 KiB
Rust
47 lines
1.2 KiB
Rust
use proc_macro2::TokenStream;
|
|
use quote::quote;
|
|
use syn::{parse::ParseStream, Expr, Path, Token};
|
|
|
|
#[derive(Default, Clone)]
|
|
pub(crate) struct CustomAttributes {
|
|
attributes: Vec<Expr>,
|
|
}
|
|
|
|
impl CustomAttributes {
|
|
/// Generates a `TokenStream` for `CustomAttributes` construction.
|
|
pub fn to_tokens(&self, bevy_reflect_path: &Path) -> TokenStream {
|
|
let attributes = self.attributes.iter().map(|value| {
|
|
quote! {
|
|
.with_attribute(#value)
|
|
}
|
|
});
|
|
|
|
quote! {
|
|
#bevy_reflect_path::attributes::CustomAttributes::default()
|
|
#(#attributes)*
|
|
}
|
|
}
|
|
|
|
/// Inserts a custom attribute into the list.
|
|
pub fn push(&mut self, value: Expr) -> syn::Result<()> {
|
|
self.attributes.push(value);
|
|
Ok(())
|
|
}
|
|
|
|
/// Is the collection empty?
|
|
pub fn is_empty(&self) -> bool {
|
|
self.attributes.is_empty()
|
|
}
|
|
|
|
/// Parse `@` (custom attribute) attribute.
|
|
///
|
|
/// Examples:
|
|
/// - `#[reflect(@Foo))]`
|
|
/// - `#[reflect(@Bar::baz("qux"))]`
|
|
/// - `#[reflect(@0..256u8)]`
|
|
pub fn parse_custom_attribute(&mut self, input: ParseStream) -> syn::Result<()> {
|
|
input.parse::<Token![@]>()?;
|
|
self.push(input.parse()?)
|
|
}
|
|
}
|