Change WhereClauseOptions::active_fields to active_types

This could have been part of #19876, which deduplicated the fields. It's
also simpler and more efficient to keep the (short-lived) active types
as an `IndexSet<Type>`, and avoid converting them to a `Vec<Type>` and
then a `Box<[Type]>`.
This commit is contained in:
Nicholas Nethercote 2025-07-01 21:36:32 +10:00
parent 33bed5dd70
commit ed1a5ab94a
2 changed files with 12 additions and 18 deletions

View File

@ -605,13 +605,11 @@ impl<'a> ReflectStruct<'a> {
} }
/// Get a collection of types which are exposed to the reflection API /// Get a collection of types which are exposed to the reflection API
pub fn active_types(&self) -> Vec<Type> { pub fn active_types(&self) -> IndexSet<Type> {
// Collect via `IndexSet` to eliminate duplicate types. // Collect into an `IndexSet` to eliminate duplicate types.
self.active_fields() self.active_fields()
.map(|field| field.reflected_type().clone()) .map(|field| field.reflected_type().clone())
.collect::<IndexSet<_>>() .collect::<IndexSet<_>>()
.into_iter()
.collect::<Vec<_>>()
} }
/// Get an iterator of fields which are exposed to the reflection API. /// Get an iterator of fields which are exposed to the reflection API.
@ -634,7 +632,7 @@ impl<'a> ReflectStruct<'a> {
} }
pub fn where_clause_options(&self) -> WhereClauseOptions { pub fn where_clause_options(&self) -> WhereClauseOptions {
WhereClauseOptions::new_with_fields(self.meta(), self.active_types().into_boxed_slice()) WhereClauseOptions::new_with_types(self.meta(), self.active_types())
} }
/// Generates a `TokenStream` for `TypeInfo::Struct` or `TypeInfo::TupleStruct` construction. /// Generates a `TokenStream` for `TypeInfo::Struct` or `TypeInfo::TupleStruct` construction.
@ -841,13 +839,11 @@ impl<'a> ReflectEnum<'a> {
} }
/// Get a collection of types which are exposed to the reflection API /// Get a collection of types which are exposed to the reflection API
pub fn active_types(&self) -> Vec<Type> { pub fn active_types(&self) -> IndexSet<Type> {
// Collect via `IndexSet` to eliminate duplicate types. // Collect into an `IndexSet` to eliminate duplicate types.
self.active_fields() self.active_fields()
.map(|field| field.reflected_type().clone()) .map(|field| field.reflected_type().clone())
.collect::<IndexSet<_>>() .collect::<IndexSet<_>>()
.into_iter()
.collect::<Vec<_>>()
} }
/// Get an iterator of fields which are exposed to the reflection API /// Get an iterator of fields which are exposed to the reflection API
@ -856,7 +852,7 @@ impl<'a> ReflectEnum<'a> {
} }
pub fn where_clause_options(&self) -> WhereClauseOptions { pub fn where_clause_options(&self) -> WhereClauseOptions {
WhereClauseOptions::new_with_fields(self.meta(), self.active_types().into_boxed_slice()) WhereClauseOptions::new_with_types(self.meta(), self.active_types())
} }
/// Returns the `GetTypeRegistration` impl as a `TokenStream`. /// Returns the `GetTypeRegistration` impl as a `TokenStream`.

View File

@ -1,5 +1,6 @@
use crate::derive_data::ReflectMeta; use crate::derive_data::ReflectMeta;
use bevy_macro_utils::fq_std::{FQAny, FQSend, FQSync}; use bevy_macro_utils::fq_std::{FQAny, FQSend, FQSync};
use indexmap::IndexSet;
use proc_macro2::{TokenStream, TokenTree}; use proc_macro2::{TokenStream, TokenTree};
use quote::{quote, ToTokens}; use quote::{quote, ToTokens};
use syn::{punctuated::Punctuated, Ident, Token, Type, WhereClause}; use syn::{punctuated::Punctuated, Ident, Token, Type, WhereClause};
@ -7,22 +8,19 @@ use syn::{punctuated::Punctuated, Ident, Token, Type, WhereClause};
/// Options defining how to extend the `where` clause for reflection. /// Options defining how to extend the `where` clause for reflection.
pub(crate) struct WhereClauseOptions<'a, 'b> { pub(crate) struct WhereClauseOptions<'a, 'b> {
meta: &'a ReflectMeta<'b>, meta: &'a ReflectMeta<'b>,
active_fields: Box<[Type]>, active_types: IndexSet<Type>,
} }
impl<'a, 'b> WhereClauseOptions<'a, 'b> { impl<'a, 'b> WhereClauseOptions<'a, 'b> {
pub fn new(meta: &'a ReflectMeta<'b>) -> Self { pub fn new(meta: &'a ReflectMeta<'b>) -> Self {
Self { Self {
meta, meta,
active_fields: Box::new([]), active_types: IndexSet::new(),
} }
} }
pub fn new_with_fields(meta: &'a ReflectMeta<'b>, active_fields: Box<[Type]>) -> Self { pub fn new_with_types(meta: &'a ReflectMeta<'b>, active_types: IndexSet<Type>) -> Self {
Self { Self { meta, active_types }
meta,
active_fields,
}
} }
pub fn meta(&self) -> &'a ReflectMeta<'b> { pub fn meta(&self) -> &'a ReflectMeta<'b> {
@ -207,7 +205,7 @@ impl<'a, 'b> WhereClauseOptions<'a, 'b> {
false false
} }
Some(self.active_fields.iter().filter_map(move |ty| { Some(self.active_types.iter().filter_map(move |ty| {
// Field type bounds are only required if `ty` is generic. How to determine that? // Field type bounds are only required if `ty` is generic. How to determine that?
// Search `ty`s token stream for identifiers that match the identifiers from the // Search `ty`s token stream for identifiers that match the identifiers from the
// function's type params. E.g. if `T` and `U` are the type param identifiers and // function's type params. E.g. if `T` and `U` are the type param identifiers and