Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
26 changes: 26 additions & 0 deletions crates/bevy_ecs/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,19 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream {
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let struct_name = &ast.ident;

let static_assert_bundle_func = syn::Ident::new(
&format!(
"static_assert_{}_does_not_have_duplicate_types",
struct_name.to_string()
),
struct_name.span(),
);

let static_assert_bundle_trait = syn::Ident::new(
&format!("{}HasDuplicateType", struct_name.to_string()),
struct_name.span(),
);

TokenStream::from(quote! {
/// SAFE: TypeInfo is returned in field-definition-order. [from_components] and [get_components] use field-definition-order
unsafe impl #impl_generics #ecs_path::bundle::Bundle for #struct_name#ty_generics #where_clause {
Expand All @@ -165,6 +178,19 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream {
#(#field_get_components)*
}
}

#[cfg(test)]
#[allow(dead_code, non_snake_case)]
fn #static_assert_bundle_func() {
macro_rules! assert_all_bundle_types_ne {
($($y:ty),+ $(,)?) => {
trait #static_assert_bundle_trait {}
$(impl #static_assert_bundle_trait for $y {})+
};
}

assert_all_bundle_types_ne!(#(#field_type),*);
}
})
}

Expand Down
13 changes: 13 additions & 0 deletions crates/bevy_ecs/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,19 @@ use std::{any::TypeId, collections::HashMap};
/// }
/// ```
///
/// ## Note
/// Bundles do not support duplicate types.
///
/// ```compile_fail
/// # use bevy_ecs::bundle::Bundle;
///
/// #[derive(Bundle)]
/// struct HasDuplicateType {
/// a: usize,
/// b: usize, // `b` is also a `usize` so this will fail to compile
/// }
/// ```
///
/// # Safety
/// [Bundle::type_info] must return the TypeInfo for each component type in the bundle, in the
/// _exact_ order that [Bundle::get_components] is called.
Expand Down