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.
This commit is contained in:
Nicholas Nethercote 2025-07-01 09:29:26 +10:00 committed by GitHub
parent 5aa520eac0
commit c7e28852cb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 11 additions and 3 deletions

View File

@ -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]

View File

@ -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<Type> {
// Collect via `IndexSet` to eliminate duplicate types.
self.active_fields()
.map(|field| field.reflected_type().clone())
.collect()
.collect::<IndexSet<_>>()
.into_iter()
.collect::<Vec<_>>()
}
/// 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<Type> {
// Collect via `IndexSet` to eliminate duplicate types.
self.active_fields()
.map(|field| field.reflected_type().clone())
.collect()
.collect::<IndexSet<_>>()
.into_iter()
.collect::<Vec<_>>()
}
/// Get an iterator of fields which are exposed to the reflection API