From 6963b58eba4fa7d8cc73389f57699ed31a8216d4 Mon Sep 17 00:00:00 2001 From: Zachary Harrold Date: Sat, 28 Sep 2024 06:23:26 +1000 Subject: [PATCH] Modify `derive_label` to support `no_std` environments (#15465) # Objective - Contributes to #15460 ## Solution - Wrap `derive_label` `quote!` in an anonymous constant which contains an `extern crate alloc` statement, allowing use of the `alloc` namespace even when a user has not brought in the crate themselves. ## Testing - CI passed locally. ## Notes We can't generate code that uses `::std::boxed::Box` in `no_std` environments, but we also can't rely on `::alloc::boxed::Box` either, since the user might not have declared `extern crate alloc`. To resolve this, the generated code is wrapped in an anonymous constant which contains the `extern crate alloc` invocation. This does mean the macro is no longer hygienic against cases where the user provides an alternate `alloc` crate, however I believe this is an acceptable compromise. Additionally, this crate itself doesn't need to be `no_std`, it just needs to _generate_ `no_std` compatible code. --------- Co-authored-by: Alice Cecile --- crates/bevy_macro_utils/src/label.rs | 29 ++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/crates/bevy_macro_utils/src/label.rs b/crates/bevy_macro_utils/src/label.rs index 6eec83c04c..1fc540c9c4 100644 --- a/crates/bevy_macro_utils/src/label.rs +++ b/crates/bevy_macro_utils/src/label.rs @@ -81,21 +81,26 @@ pub fn derive_label( .unwrap(), ); quote! { - impl #impl_generics #trait_path for #ident #ty_generics #where_clause { - fn dyn_clone(&self) -> ::std::boxed::Box { - ::std::boxed::Box::new(::core::clone::Clone::clone(self)) - } + // To ensure alloc is available, but also prevent its name from clashing, we place the implementation inside an anonymous constant + const _: () = { + extern crate alloc; - fn as_dyn_eq(&self) -> &dyn #dyn_eq_path { - self - } + impl #impl_generics #trait_path for #ident #ty_generics #where_clause { + fn dyn_clone(&self) -> alloc::boxed::Box { + alloc::boxed::Box::new(::core::clone::Clone::clone(self)) + } - fn dyn_hash(&self, mut state: &mut dyn ::core::hash::Hasher) { - let ty_id = ::core::any::TypeId::of::(); - ::core::hash::Hash::hash(&ty_id, &mut state); - ::core::hash::Hash::hash(self, &mut state); + fn as_dyn_eq(&self) -> &dyn #dyn_eq_path { + self + } + + fn dyn_hash(&self, mut state: &mut dyn ::core::hash::Hasher) { + let ty_id = ::core::any::TypeId::of::(); + ::core::hash::Hash::hash(&ty_id, &mut state); + ::core::hash::Hash::hash(self, &mut state); + } } - } + }; } .into() }