diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/enum_utility.rs b/crates/bevy_reflect/bevy_reflect_derive/src/enum_utility.rs index 230e0876c6b6c9..af6037f6c563c0 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/enum_utility.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/enum_utility.rs @@ -1,6 +1,6 @@ use crate::{ derive_data::{EnumVariantFields, ReflectEnum}, - utility::field_ident_or_indexed, + utility::ident_or_index, }; use proc_macro2::Ident; use quote::{quote, ToTokens}; @@ -36,7 +36,7 @@ pub(crate) fn get_variant_constructors( }; let mut reflect_index: usize = 0; let constructor_fields = fields.iter().enumerate().map(|(declar_index, field)| { - let field_ident = field_ident_or_indexed(declar_index, field.data.ident.as_ref()); + let field_ident = ident_or_index(field.data.ident.as_ref(), declar_index); let field_value = if field.attrs.ignore { quote! { Default::default() } } else { diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs index db1e10bb2fcb42..3c982f55f8c612 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs @@ -291,7 +291,7 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden } (reflect_idx, constructor_argument) } - let mut info_type = |variant, info_type, arguments| { + let mut add_fields_branch = |variant, info_type, arguments, field_len| { let variant = Ident::new(variant, Span::call_site()); let info_type = Ident::new(info_type, Span::call_site()); variant_info.push(quote! { @@ -299,14 +299,20 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden #bevy_reflect_path::#info_type::new(#arguments) ) }); - variant + enum_field_len.push(quote! { + #unit{..} => #field_len + }); + enum_variant_name.push(quote! { + #unit{..} => #name + }); + enum_variant_type.push(quote! { + #unit{..} => #bevy_reflect_path::VariantType::#variant + }); }; - let (variant, field_len) = match &variant.fields { + match &variant.fields { EnumVariantFields::Unit => { - let variant = info_type("Unit", "UnitVariantInfo", quote!(#name)); - (variant, 0usize) + add_fields_branch("Unit", "UnitVariantInfo", quote!(#name), 0usize); } - EnumVariantFields::Unnamed(fields) => { let (field_len, argument) = for_fields(fields, |reflect_idx, declar, field| { let declar_field = syn::Index::from(declar); @@ -317,8 +323,7 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden quote! { #bevy_reflect_path::UnnamedField::new::<#field_ty>(#reflect_idx) } }); let arguments = quote!(#name, &[ #(#argument),* ]); - let variant = info_type("Tuple", "TupleVariantInfo", arguments); - (variant, field_len) + add_fields_branch("Tuple", "TupleVariantInfo", arguments, field_len); } EnumVariantFields::Named(fields) => { let (field_len, argument) = for_fields(fields, |reflect_idx, _, field| { @@ -341,19 +346,9 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden quote! { #bevy_reflect_path::NamedField::new::<#field_ty, _>(#field_name) } }); let arguments = quote!(#name, &[ #(#argument),* ]); - let variant = info_type("Struct", "StructVariantInfo", arguments); - (variant, field_len) + add_fields_branch("Struct", "StructVariantInfo", arguments, field_len); } }; - enum_field_len.push(quote! { - #unit{..} => #field_len - }); - enum_variant_name.push(quote! { - #unit{..} => #name - }); - enum_variant_type.push(quote! { - #unit{..} => #bevy_reflect_path::VariantType::#variant - }); } EnumImpls { diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs index 9c79f40200fc7d..a5e3cd49da73ba 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs @@ -29,10 +29,29 @@ pub(crate) struct ResultSifter { errors: Option, } -pub(crate) fn field_ident_or_indexed(index: usize, ident: Option<&Ident>) -> Member { - ident.as_ref().map_or_else( +/// Returns a `Member` made of `ident` or `index` if `ident` is None. +/// +/// Rust struct syntax allows for `Struct { foo: "string" }` with explicitly +/// named fields. It allows the `Struct { 0: "string" }` syntax when the struct +/// is declared as a tuple struct. +/// +/// ``` +/// # fn main() { +/// struct Foo { field: &'static str } +/// struct Bar(&'static str); +/// let Foo { field } = Foo { field: "hi" }; +/// let Bar { 0: field } = Bar { 0: "hello" }; +/// let Bar(field) = Bar("hello"); // more common syntax +/// # } +/// ``` +/// +/// This function helps field access in context where you are declaring either +/// a tuple struct or a struct with named fields. If you don't have a field name, +/// it means you need to access the struct through an index. +pub(crate) fn ident_or_index(ident: Option<&Ident>, index: usize) -> Member { + ident.map_or_else( || Member::Unnamed(index.into()), - |&ident| Member::Named(ident.clone()), + |ident| Member::Named(ident.clone()), ) }