From 85448b767e40f3347523282520f47d662f1f9204 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Sat, 28 Jun 2025 22:45:41 -0400 Subject: [PATCH] Make `DebugName` work when building with no default features (#19824) # Objective Let `bevy_utils` build with no default features. `cargo build -p bevy_utils --no-default-features` currently fails with ``` error[E0433]: failed to resolve: use of unresolved module or unlinked crate `alloc` --> crates\bevy_utils\src\debug_info.rs:1:5 | 1 | use alloc::{borrow::Cow, fmt, string::String}; | ^^^^^ use of unresolved module or unlinked crate `alloc` | = help: add `extern crate alloc` to use the `alloc` crate error[E0432]: unresolved import `alloc` --> crates\bevy_utils\src\debug_info.rs:1:5 | 1 | use alloc::{borrow::Cow, fmt, string::String}; | ^^^^^ help: a similar path exists: `core::alloc` ``` I would have expected CI to catch this earlier, but I have not investigated why it did not. ## Solution Wrap the parts of `DebugName` that use `Cow` and `String` in `cfg::alloc!`. If the `debug` feature is enabled, then `DebugName` itself stores a `Cow`, so make the `debug` feature require `bevy_platform/alloc`. That is, you can use `DebugName` in no-std contexts when it's just a ZST! (I bet it's even possible to support no-std `debug` by storing `&'static str` instead of `Cow<'static, str>`, but that seemed like too much complexity for now.) --- crates/bevy_utils/Cargo.toml | 2 +- crates/bevy_utils/src/debug_info.rs | 61 +++++++++++++++++------------ 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/crates/bevy_utils/Cargo.toml b/crates/bevy_utils/Cargo.toml index 4e74e6ea94..447c9966f4 100644 --- a/crates/bevy_utils/Cargo.toml +++ b/crates/bevy_utils/Cargo.toml @@ -18,7 +18,7 @@ parallel = ["bevy_platform/std", "dep:thread_local"] std = ["disqualified/alloc"] -debug = [] +debug = ["bevy_platform/alloc"] [dependencies] bevy_platform = { path = "../bevy_platform", version = "0.17.0-dev", default-features = false } diff --git a/crates/bevy_utils/src/debug_info.rs b/crates/bevy_utils/src/debug_info.rs index c79c5ebe60..84232c9d3d 100644 --- a/crates/bevy_utils/src/debug_info.rs +++ b/crates/bevy_utils/src/debug_info.rs @@ -1,4 +1,7 @@ -use alloc::{borrow::Cow, fmt, string::String}; +use crate::cfg; +cfg::alloc! { + use alloc::{borrow::Cow, fmt, string::String}; +} #[cfg(feature = "debug")] use core::any::type_name; use disqualified::ShortName; @@ -16,14 +19,16 @@ pub struct DebugName { name: Cow<'static, str>, } -impl fmt::Display for DebugName { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - #[cfg(feature = "debug")] - f.write_str(self.name.as_ref())?; - #[cfg(not(feature = "debug"))] - f.write_str(FEATURE_DISABLED)?; +cfg::alloc! { + impl fmt::Display for DebugName { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + #[cfg(feature = "debug")] + f.write_str(self.name.as_ref())?; + #[cfg(not(feature = "debug"))] + f.write_str(FEATURE_DISABLED)?; - Ok(()) + Ok(()) + } } } @@ -39,14 +44,16 @@ impl DebugName { } } - /// Create a new `DebugName` from a `String` - /// - /// The value will be ignored if the `debug` feature is not enabled - #[cfg_attr(not(feature = "debug"), expect(unused_variables))] - pub fn owned(value: String) -> Self { - DebugName { - #[cfg(feature = "debug")] - name: Cow::Owned(value), + cfg::alloc! { + /// Create a new `DebugName` from a `String` + /// + /// The value will be ignored if the `debug` feature is not enabled + #[cfg_attr(not(feature = "debug"), expect(unused_variables))] + pub fn owned(value: String) -> Self { + DebugName { + #[cfg(feature = "debug")] + name: Cow::Owned(value), + } } } @@ -79,19 +86,21 @@ impl DebugName { } } -impl From> for DebugName { - #[cfg_attr(not(feature = "debug"), expect(unused_variables))] - fn from(value: Cow<'static, str>) -> Self { - Self { - #[cfg(feature = "debug")] - name: value, +cfg::alloc! { + impl From> for DebugName { + #[cfg_attr(not(feature = "debug"), expect(unused_variables))] + fn from(value: Cow<'static, str>) -> Self { + Self { + #[cfg(feature = "debug")] + name: value, + } } } -} -impl From for DebugName { - fn from(value: String) -> Self { - Self::owned(value) + impl From for DebugName { + fn from(value: String) -> Self { + Self::owned(value) + } } }