Modify derive_label to support no_std environments#15465
Modify derive_label to support no_std environments#15465alice-i-cecile merged 2 commits intobevyengine:mainfrom
derive_label to support no_std environments#15465Conversation
We can't generate code that uses `::std::boxed::Box` in `no_std` environments, but we also can't rely on `::alloc::boxed::Box`, 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.
| fn dyn_clone(&self) -> ::std::boxed::Box<dyn #trait_path> { | ||
| ::std::boxed::Box::new(::core::clone::Clone::clone(self)) | ||
| } | ||
| const _: () = { |
There was a problem hiding this comment.
If you check the description of the PR the goal is to allow invoking this macro in no_std crates, which is required for Bevy to become no_std.
We would normally use the fully qualified name:
::std::boxed::BoxHowever, in no_std we can't use the std namespace, so instead we need to use the original definition of Box in the alloc crate:
::alloc::boxed::BoxBut that also doesn't work, because access to the alloc namespace requires explicitly linking it in the end-user's crate:
extern crate alloc;So we need to include that extern statement. However, we can't place it in the global namespace, because it would then clash with other macro invocations.
To ensure alloc is available, but also prevent its name from clashing, we place the implementation inside an anonymous constant:
const _: () = {
// private namespace so no clashes
};There was a problem hiding this comment.
Just not understand why code put in const _: () = { ... }. Thanks for detailed explanation!
) # Objective - Contributes to bevyengine#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 <alice.i.cecile@gmail.com>
) # Objective - Contributes to bevyengine#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 <alice.i.cecile@gmail.com>
Objective
no_stdBevy #15460Solution
derive_labelquote!in an anonymous constant which contains anextern crate allocstatement, allowing use of theallocnamespace even when a user has not brought in the crate themselves.Testing
Notes
We can't generate code that uses
::std::boxed::Boxinno_stdenvironments, but we also can't rely on::alloc::boxed::Boxeither, since the user might not have declaredextern crate alloc. To resolve this, the generated code is wrapped in an anonymous constant which contains theextern crate allocinvocation.This does mean the macro is no longer hygienic against cases where the user provides an alternate
alloccrate, however I believe this is an acceptable compromise.Additionally, this crate itself doesn't need to be
no_std, it just needs to generateno_stdcompatible code.