Skip to content

Reflect auto registration #15030

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 66 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
4b48e23
minimal example auto registration for reflect types
eugineerd Sep 2, 2024
89c52dd
implement auto registration for the rest of supported `#[derive(Refle…
eugineerd Sep 3, 2024
f3614b8
add `no_auto_register` reflect attribute to allow opting out of autom…
eugineerd Sep 3, 2024
7367345
added `reflect_auto_register` feature to allow enabling/disabling aut…
eugineerd Sep 3, 2024
16ee7cf
reduce wasm overhead
eugineerd Sep 4, 2024
35f0591
run `cargo run -p build-templated-pages -- update features`
eugineerd Sep 4, 2024
119a598
fix not registering `TypeData`
eugineerd Sep 4, 2024
53696f7
add doc test and remove feature-gating
eugineerd Sep 5, 2024
7d761e1
remove `dbg!`
eugineerd Sep 5, 2024
d8eb597
update examples for automatic reflect type registration
eugineerd Sep 5, 2024
1da577a
fix typo
eugineerd Sep 5, 2024
4485798
remove outdated comment from reflect Cargo.toml
eugineerd Sep 5, 2024
ef6bb2d
remove needless borrow
eugineerd Sep 5, 2024
5fa1572
fix from check-doc
eugineerd Sep 5, 2024
d2d3290
move calling automatic type registration to `AppTypeRegistry`.
eugineerd Sep 5, 2024
878e8d3
more clippy fixes
eugineerd Sep 5, 2024
b518d5e
Move automatic types registration to app creation
eugineerd Sep 5, 2024
edf5f87
revert changes to examples that use `TypeRegistry`
eugineerd Sep 6, 2024
e9f67f0
hide automatic reflect registration in `__macro_exports`
eugineerd Sep 6, 2024
301b60a
add note about `no_auto_register` to `Reflect` derive doc
eugineerd Sep 6, 2024
6ad0a23
made `inventory` and `wasm-init` platform specific deps
eugineerd Sep 7, 2024
1279d62
tried to abstract platform-dependent code away
eugineerd Sep 7, 2024
74337f7
update `bevy_reflect`'s module-level doc's "Manual Registration" section
eugineerd Sep 7, 2024
7723de5
Merge remote-tracking branch 'upstream/main' into reflect-auto-regist…
eugineerd Oct 2, 2024
b18b645
Merge remote-tracking branch 'upstream/main' into reflect-auto-regist…
eugineerd Oct 20, 2024
257af97
Merge branch 'main' into reflect-auto-registration
eugineerd Dec 1, 2024
943dde9
added test for ignored auto reflect registration
eugineerd Dec 1, 2024
36f49f0
clippy
eugineerd Dec 1, 2024
e50610b
apply suggested doc fix
eugineerd Dec 1, 2024
b0f2438
implement reflect auto register for opaque types
eugineerd Dec 1, 2024
2ae4bb9
add test for auto reflect registration on all supported types
eugineerd Dec 1, 2024
7c7bd79
put automatic type registration behind feature gate
eugineerd Dec 1, 2024
03ce543
add reason to `no_auto_register` allow
eugineerd Dec 1, 2024
67f4d02
use `impl_is_generic` instead of converting to token stream.
eugineerd Dec 1, 2024
1548654
Merge remote-tracking branch 'upstream/main' into reflect-auto-regist…
eugineerd Dec 8, 2024
69bbc17
fix missing `[package]` in `bevy_reflect/Cargo.toml` (How did that ev…
eugineerd Dec 8, 2024
e82d33c
Merge branch 'main' into reflect-auto-registration
eugineerd Jan 4, 2025
58b847c
add `no_std` support on wasm
eugineerd Jan 4, 2025
95593d1
feature-gate `no_auto_register` attribute getter
eugineerd Jan 5, 2025
e18aaef
Merge branch 'main' of https://github.com/bevyengine/bevy into reflec…
eugineerd Jan 20, 2025
42db5e0
Merge branch 'main' of https://github.com/bevyengine/bevy into reflec…
eugineerd Feb 21, 2025
1bb9ee8
remove `wasm-init` and just use `inventory` instead
eugineerd Feb 21, 2025
c6be4fa
Merge branch 'main' of https://github.com/bevyengine/bevy into reflec…
eugineerd Feb 25, 2025
7756f4b
Merge branch 'main' of https://github.com/bevyengine/bevy into reflec…
eugineerd Mar 12, 2025
2eb5d1b
remove empty enum from tests
eugineerd Mar 12, 2025
1448ee6
Disable auto registration by default
eugineerd Mar 12, 2025
54ac872
update features
eugineerd Mar 12, 2025
098cff9
Revert "remove empty enum from tests"
eugineerd Mar 20, 2025
eb66a7b
Merge branch 'main' into reflect-auto-registration-staticlib
eugineerd Mar 20, 2025
21a5ba0
implement automatic type registrations without relying on `inventory`
eugineerd Mar 25, 2025
fa60c51
add an example for static automatic registration
eugineerd Mar 25, 2025
2958700
Add `auto_register_inventory` feature to `bevy_reflect`
eugineerd Mar 25, 2025
2433fd6
example types fixes
eugineerd Mar 25, 2025
4d2a9c3
Merge branch 'main' of https://github.com/bevyengine/bevy into reflec…
eugineerd Apr 3, 2025
ff78027
fix `auto_register_static` example
eugineerd Apr 17, 2025
8ba6dad
enable `auto_register_inventory` by default for `bevy_reflect`
eugineerd Apr 17, 2025
da7768b
update examples readme
eugineerd Apr 17, 2025
22e6f27
fix markdownlint errors
eugineerd Apr 17, 2025
9671223
typos
eugineerd Apr 17, 2025
ded6b15
Merge branch 'main' of https://github.com/bevyengine/bevy into reflec…
eugineerd Apr 17, 2025
e257d75
fix trailing spaces
eugineerd Apr 17, 2025
7c60aa8
fix `wasm_support` path
eugineerd Apr 17, 2025
202e59f
use proper calling convention for extern fns
eugineerd Apr 18, 2025
d6a254f
remove some unsafe from `auto_register_static`
eugineerd Apr 18, 2025
567683a
add release notes
eugineerd Apr 25, 2025
b49063d
markdown lints
eugineerd Apr 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ members = [
"examples/mobile",
# Examples of using Bevy on no_std platforms.
"examples/no_std/*",
# Examples of compiling Bevy with automatic reflect type registration for platforms without `inventory` support.
"examples/reflection/auto_register_static",
# Benchmarks
"benches",
# Internal tools that are not published.
Expand Down Expand Up @@ -157,6 +159,7 @@ default = [
"hdr",
"multi_threaded",
"png",
"reflect_auto_register",
Copy link
Member

@cart cart Mar 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This being enabled by default means that we are unlikely to catch new types that we forget to register. I am certain that over time Bevy's type registry completeness would degrade.

Likewise, plugin authors will be insulated from this by default, so I suspect the ecosystem would effectively just not care about this. This isn't the kind of problem you can solve by adding a "please register your types manually" to the "Bevy plugin guidelines" doc. This problem will be hidden from pretty much everyone, and I suspect most people that are aware will choose the path of least resistance.

Given that, I am uncomfortable backing us into this corner when we don't know how this approach will fare on future platforms. The entire ecosystem falling apart when we add, say, PS5 support doesn't feel stomach-able to me. Related: would this throw a wrench in @bushrat011899's no_std / niche platform work? (as in, does auto-registration work on the platforms targeted by the current no_std work, and therefore would the "ecosystem and internal Bevy breakage problem" apply there)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re. no_std: inventory relies on linker tricks which are added on a platform-by-platform basis in the inventory crate. That is, there's no way for an end user on an unsupported platform to add that support themselves, short of upstream efforts in inventory. At least, that's my understanding of the crate.

As for what platforms inventory currently supports, it appears to be WebAssembly, and most operating systems. I don't see any support for no-OS platforms like embedded or retro consoles.

That's fine IMO, because not every Bevy feature needs to work on embedded. But as Cart points out, this does have the potential side effect of making libraries "lazy", breaking their reflection support on no_std or just not bothering with no_std at all.

Personally, I would like this feature to be included, but as an option. It's a lot easier to recommend users making a game enable this feature than it is to recommend library authors disable it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed reflect_auto_register from default features and reverted documentation and examples changes using it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added static approach as a fallback for platforms that aren't supported by inventory, this should be fine to enable by default now.

"smaa_luts",
"sysinfo_plugin",
"tonemapping_luts",
Expand Down Expand Up @@ -516,6 +519,12 @@ reflect_functions = ["bevy_internal/reflect_functions"]
# Enable documentation reflection
reflect_documentation = ["bevy_internal/reflect_documentation"]

# Enable automatic reflect registration
reflect_auto_register = ["bevy_internal/reflect_auto_register"]

# Enable automatic reflect registration without inventory. See `reflect::load_type_registrations` for more info.
reflect_auto_register_static = ["bevy_internal/reflect_auto_register_static"]

# Enable winit custom cursor support
custom_cursor = ["bevy_internal/custom_cursor"]

Expand Down Expand Up @@ -2664,6 +2673,17 @@ description = "Demonstrates how to create and use type data"
category = "Reflection"
wasm = false

[[example]]
name = "auto_register_static"
path = "examples/reflection/auto_register_static/src/lib.rs"
doc-scrape-examples = true

[package.metadata.example.auto_register_static]
name = "Automatic types registration"
description = "Demonstrates how to set up automatic reflect types registration for platforms without `inventory` support"
category = "Reflection"
wasm = false

# Scene
[[example]]
name = "scene"
Expand Down
5 changes: 5 additions & 0 deletions crates/bevy_app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ reflect_functions = [
"bevy_reflect/functions",
"bevy_ecs/reflect_functions",
]
reflect_auto_register = [
"bevy_reflect",
"bevy_reflect/auto_register",
"bevy_ecs/reflect_auto_register",
]

# Debugging Features

Expand Down
5 changes: 5 additions & 0 deletions crates/bevy_app/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,12 @@ impl Default for App {

#[cfg(feature = "bevy_reflect")]
{
#[cfg(not(feature = "reflect_auto_register"))]
app.init_resource::<AppTypeRegistry>();

#[cfg(feature = "reflect_auto_register")]
app.insert_resource(AppTypeRegistry::new_with_derived_types());

app.register_type::<Name>();
app.register_type::<ChildOf>();
app.register_type::<Children>();
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ bevy_reflect = ["dep:bevy_reflect"]

## Extends reflection support to functions.
reflect_functions = ["bevy_reflect", "bevy_reflect/functions"]
reflect_auto_register = ["bevy_reflect", "bevy_reflect/auto_register"]

## Use the configurable global error handler as the default error handler.
##
Expand Down
12 changes: 12 additions & 0 deletions crates/bevy_ecs/src/reflect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ impl DerefMut for AppTypeRegistry {
}
}

impl AppTypeRegistry {
/// Creates [`AppTypeRegistry`] and automatically registers all types deriving [`Reflect`].
///
/// See [`TypeRegistry::register_derived_types`] for more details.
#[cfg(feature = "reflect_auto_register")]
pub fn new_with_derived_types() -> Self {
let app_registry = AppTypeRegistry::default();
app_registry.write().register_derived_types();
app_registry
}
}

/// A [`Resource`] storing [`FunctionRegistry`] for
/// function registrations relevant to a whole app.
///
Expand Down
14 changes: 14 additions & 0 deletions crates/bevy_internal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,20 @@ reflect_functions = [
"bevy_ecs/reflect_functions",
]

# Enable automatic reflect registration using inventory.
reflect_auto_register = [
"bevy_reflect/auto_register_inventory",
"bevy_app/reflect_auto_register",
"bevy_ecs/reflect_auto_register",
]

# Enable automatic reflect registration without inventory. See `reflect::load_type_registrations` for more info.
reflect_auto_register_static = [
"bevy_reflect/auto_register_static",
"bevy_app/reflect_auto_register",
"bevy_ecs/reflect_auto_register",
]

# Enable documentation reflection
reflect_documentation = ["bevy_reflect/documentation"]

Expand Down
21 changes: 20 additions & 1 deletion crates/bevy_reflect/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ keywords = ["bevy"]
rust-version = "1.85.0"

[features]
default = ["std", "smallvec", "debug"]
default = ["std", "smallvec", "debug", "auto_register_inventory"]

# Features

Expand Down Expand Up @@ -69,6 +69,22 @@ critical-section = [
"bevy_utils/critical-section",
]

# Enables automatic reflect registration. Does nothing by itself,
# must select `auto_register_inventory` or `auto_register_static` to make it work.
auto_register = []
## Enables automatic reflect registration using inventory. Not supported on all platforms.
auto_register_inventory = [
"auto_register",
"bevy_reflect_derive/auto_register_inventory",
"dep:inventory",
]
## Enable automatic reflect registration without inventory. This feature has precedence over `auto_register_inventory`.
## See `load_type_registrations` for more info.
auto_register_static = [
"auto_register",
"bevy_reflect_derive/auto_register_static",
]

## Enables use of browser APIs.
## Note this is currently only applicable on `wasm32` architectures.
web = ["bevy_platform/web", "uuid?/js"]
Expand Down Expand Up @@ -115,6 +131,9 @@ wgpu-types = { version = "24", features = [
"serde",
], optional = true, default-features = false }

# deps for automatic type registration
inventory = { version = "0.3", optional = true }

[dev-dependencies]
ron = "0.8.0"
rmp-serde = "1.1"
Expand Down
7 changes: 7 additions & 0 deletions crates/bevy_reflect/derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ default = []
documentation = []
# Enables macro logic related to function reflection
functions = []
# Enables automatic reflect registration. Does nothing by itself,
# must select `auto_register_inventory` or `auto_register_static` to make it work.
auto_register = []
# Enables automatic reflection using inventory. Not supported on all platforms.
auto_register_inventory = ["auto_register"]
# Enables automatic reflection on platforms not supported by inventory. See `load_type_registrations` for more info.
auto_register_static = ["auto_register"]

[dependencies]
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.16.0-dev" }
Expand Down
20 changes: 20 additions & 0 deletions crates/bevy_reflect/derive/src/container_attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ mod kw {
syn::custom_keyword!(Hash);
syn::custom_keyword!(Clone);
syn::custom_keyword!(no_field_bounds);
syn::custom_keyword!(no_auto_register);
syn::custom_keyword!(opaque);
}

Expand Down Expand Up @@ -184,6 +185,7 @@ pub(crate) struct ContainerAttributes {
type_path_attrs: TypePathAttrs,
custom_where: Option<WhereClause>,
no_field_bounds: bool,
no_auto_register: bool,
custom_attributes: CustomAttributes,
is_opaque: bool,
idents: Vec<Ident>,
Expand Down Expand Up @@ -240,6 +242,8 @@ impl ContainerAttributes {
self.parse_no_field_bounds(input)
} else if lookahead.peek(kw::Clone) {
self.parse_clone(input)
} else if lookahead.peek(kw::no_auto_register) {
self.parse_no_auto_register(input)
} else if lookahead.peek(kw::Debug) {
self.parse_debug(input)
} else if lookahead.peek(kw::Hash) {
Expand Down Expand Up @@ -378,6 +382,16 @@ impl ContainerAttributes {
Ok(())
}

/// Parse `no_auto_register` attribute.
///
/// Examples:
/// - `#[reflect(no_auto_register)]`
fn parse_no_auto_register(&mut self, input: ParseStream) -> syn::Result<()> {
input.parse::<kw::no_auto_register>()?;
self.no_auto_register = true;
Ok(())
}

/// Parse `where` attribute.
///
/// Examples:
Expand Down Expand Up @@ -583,6 +597,12 @@ impl ContainerAttributes {
self.no_field_bounds
}

/// Returns true if the `no_auto_register` attribute was found on this type.
#[cfg(feature = "auto_register")]
pub fn no_auto_register(&self) -> bool {
self.no_auto_register
}

/// Returns true if the `opaque` attribute was found on this type.
pub fn is_opaque(&self) -> bool {
self.is_opaque
Expand Down
69 changes: 69 additions & 0 deletions crates/bevy_reflect/derive/src/impls/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,72 @@ pub fn common_partial_reflect_methods(
#debug_fn
}
}

#[cfg(feature = "auto_register")]
pub fn reflect_auto_registration(meta: &ReflectMeta) -> Option<proc_macro2::TokenStream> {
if meta.attrs().no_auto_register() {
return None;
}

let bevy_reflect_path = meta.bevy_reflect_path();
let type_path = meta.type_path();

if type_path.impl_is_generic() {
return None;
};

if cfg!(feature = "auto_register_static") {
use std::{env, fs, io::Write, path::PathBuf, sync::LazyLock, sync::Mutex};

// Names of registrations functions will be stored in this file.
// To allow writing to this file from multiple threads during compilation it is protected by mutex.
// This static is valid for the duration of compilation of one crate and we have one file per crate,
// so it is enough to protect compilation threads from overwriting each other.
// This file is reset on every recompilation.
static REGISTRATION_FNS_EXPORT: LazyLock<Mutex<fs::File>> = LazyLock::new(|| {
let path = PathBuf::from("target").join("type_registrations");
fs::DirBuilder::new()
.recursive(true)
.create(&path)
.unwrap_or_else(|_| panic!("Failed to create {:?}", path));
let file_path = path.join(
env::var("CARGO_CRATE_NAME")
.expect("Expected cargo to set CARGO_CRATE_NAME env var"),
);
let file = fs::OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(&file_path)
.unwrap_or_else(|_| panic!("Failed to create {:?}", file_path));
Mutex::new(file)
});

let export_name = format!("_bevy_reflect_register_{}", uuid::Uuid::new_v4().as_u128());
if env::var("BEVY_REFLECT_AUTO_REGISTER_STATIC").is_ok_and(|v| v != "0") {
let mut file = REGISTRATION_FNS_EXPORT.lock().unwrap();
writeln!(file, "{}", export_name)
.unwrap_or_else(|_| panic!("Failed to write registration function"));
// We must sync_data to ensure all content is written before releasing the mutex.
file.sync_data().unwrap();
};
Some(quote! {
/// # Safety
/// This function must only be used by the `load_type_registrations` macro.
#[unsafe(export_name=#export_name)]
pub unsafe extern "Rust" fn bevy_register_type(registry: &mut #bevy_reflect_path::TypeRegistry) {
<#type_path as #bevy_reflect_path::__macro_exports::RegisterForReflection>::__register(registry);
}
})
} else if cfg!(feature = "auto_register_inventory") {
Some(quote! {
#bevy_reflect_path::__macro_exports::auto_register::inventory::submit!{
#bevy_reflect_path::__macro_exports::auto_register::AutomaticReflectRegistrations(
<#type_path as #bevy_reflect_path::__macro_exports::auto_register::RegisterForReflection>::__register
)
}
})
} else {
None
}
}
7 changes: 7 additions & 0 deletions crates/bevy_reflect/derive/src/impls/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream
let (impl_generics, ty_generics, where_clause) =
reflect_enum.meta().type_path().generics().split_for_impl();

#[cfg(not(feature = "auto_register"))]
let auto_register = None::<proc_macro2::TokenStream>;
#[cfg(feature = "auto_register")]
let auto_register = crate::impls::reflect_auto_registration(reflect_enum.meta());

let where_reflect_clause = where_clause_options.extend_where_clause(where_clause);

quote! {
Expand All @@ -96,6 +101,8 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream

#function_impls

#auto_register

impl #impl_generics #bevy_reflect_path::Enum for #enum_path #ty_generics #where_reflect_clause {
fn field(&self, #ref_name: &str) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> {
match #match_this {
Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_reflect/derive/src/impls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ mod tuple_structs;
mod typed;

pub(crate) use assertions::impl_assertions;
#[cfg(feature = "auto_register")]
pub(crate) use common::reflect_auto_registration;
pub(crate) use common::{common_partial_reflect_methods, impl_full_reflect};
pub(crate) use enums::impl_enum;
#[cfg(feature = "functions")]
Expand Down
7 changes: 7 additions & 0 deletions crates/bevy_reflect/derive/src/impls/opaque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ pub(crate) fn impl_opaque(meta: &ReflectMeta) -> proc_macro2::TokenStream {
#[cfg(feature = "functions")]
let function_impls = crate::impls::impl_function_traits(meta, &where_clause_options);

#[cfg(not(feature = "auto_register"))]
let auto_register = None::<proc_macro2::TokenStream>;
#[cfg(feature = "auto_register")]
let auto_register = crate::impls::reflect_auto_registration(meta);

let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl();
let where_reflect_clause = where_clause_options.extend_where_clause(where_clause);
let get_type_registration_impl = meta.get_type_registration(&where_clause_options);
Expand All @@ -71,6 +76,8 @@ pub(crate) fn impl_opaque(meta: &ReflectMeta) -> proc_macro2::TokenStream {

#function_impls

#auto_register

impl #impl_generics #bevy_reflect_path::PartialReflect for #type_path #ty_generics #where_reflect_clause {
#[inline]
fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> {
Expand Down
7 changes: 7 additions & 0 deletions crates/bevy_reflect/derive/src/impls/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS
.generics()
.split_for_impl();

#[cfg(not(feature = "auto_register"))]
let auto_register = None::<proc_macro2::TokenStream>;
#[cfg(feature = "auto_register")]
let auto_register = crate::impls::reflect_auto_registration(reflect_struct.meta());

let where_reflect_clause = where_clause_options.extend_where_clause(where_clause);

quote! {
Expand All @@ -76,6 +81,8 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS

#function_impls

#auto_register

impl #impl_generics #bevy_reflect_path::Struct for #struct_path #ty_generics #where_reflect_clause {
fn field(&self, name: &str) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> {
match name {
Expand Down
7 changes: 7 additions & 0 deletions crates/bevy_reflect/derive/src/impls/tuple_structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2::
.generics()
.split_for_impl();

#[cfg(not(feature = "auto_register"))]
let auto_register = None::<proc_macro2::TokenStream>;
#[cfg(feature = "auto_register")]
let auto_register = crate::impls::reflect_auto_registration(reflect_struct.meta());

let where_reflect_clause = where_clause_options.extend_where_clause(where_clause);

quote! {
Expand All @@ -64,6 +69,8 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2::

#function_impls

#auto_register

impl #impl_generics #bevy_reflect_path::TupleStruct for #struct_path #ty_generics #where_reflect_clause {
fn field(&self, index: usize) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> {
match index {
Expand Down
Loading