From c7e28852cb773b562a84795d382b4593756d3d94 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Jul 2025 09:29:26 +1000 Subject: [PATCH] bevy_reflect: avoid duplicate type bounds in derived methods (#19876) # Objective Most of the impls derived for `#[derive(Reflect)]` have one set of type bounds per field, like so: ``` f32: ::bevy::reflect::FromReflect + ::bevy::reflect::TypePath + ::bevy::reflect::MaybeTyped + ::bevy::reflect::__macro_exports::RegisterForReflection, ``` If multiple fields have the same type, the bounds are repeated uselessly. This can only hurt compile time and clogs up the `cargo expand` output. Avoiding this will help with https://github.com/bevyengine/bevy/issues/19873. ## Solution Use a hashset when collecting the bounds to eliminate duplicates. ## Testing I used cargo expand to confirm the duplicate bounds are no longer produced. `-Zmacro-stats` outputs tells me this reduces the size of the `Reflect` code produced for `bevy_ui` from 1_544_696 bytes to 1_467_967 bytes, a 5% drop. --- crates/bevy_reflect/derive/Cargo.toml | 3 ++- crates/bevy_reflect/derive/src/derive_data.rs | 11 +++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/crates/bevy_reflect/derive/Cargo.toml b/crates/bevy_reflect/derive/Cargo.toml index 032046ae2f..b9eaa369cd 100644 --- a/crates/bevy_reflect/derive/Cargo.toml +++ b/crates/bevy_reflect/derive/Cargo.toml @@ -20,9 +20,10 @@ functions = [] [dependencies] bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.17.0-dev" } +indexmap = "2.0" proc-macro2 = "1.0" quote = "1.0" -syn = { version = "2.0", features = ["full"] } +syn = { version = "2.0", features = ["full", "extra-traits"] } uuid = { version = "1.13.1", features = ["v4"] } [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/crates/bevy_reflect/derive/src/derive_data.rs b/crates/bevy_reflect/derive/src/derive_data.rs index a0343f619f..614f357b37 100644 --- a/crates/bevy_reflect/derive/src/derive_data.rs +++ b/crates/bevy_reflect/derive/src/derive_data.rs @@ -1,4 +1,5 @@ use core::fmt; +use indexmap::IndexSet; use proc_macro2::Span; use crate::{ @@ -607,9 +608,12 @@ impl<'a> ReflectStruct<'a> { /// Get a collection of types which are exposed to the reflection API pub fn active_types(&self) -> Vec { + // Collect via `IndexSet` to eliminate duplicate types. self.active_fields() .map(|field| field.reflected_type().clone()) - .collect() + .collect::>() + .into_iter() + .collect::>() } /// Get an iterator of fields which are exposed to the reflection API. @@ -851,9 +855,12 @@ impl<'a> ReflectEnum<'a> { /// Get a collection of types which are exposed to the reflection API pub fn active_types(&self) -> Vec { + // Collect via `IndexSet` to eliminate duplicate types. self.active_fields() .map(|field| field.reflected_type().clone()) - .collect() + .collect::>() + .into_iter() + .collect::>() } /// Get an iterator of fields which are exposed to the reflection API