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.)
This commit is contained in:
Chris Russell 2025-06-28 22:45:41 -04:00 committed by GitHub
parent 57e58ef997
commit 85448b767e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 36 additions and 27 deletions

View File

@ -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 }

View File

@ -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<Cow<'static, str>> 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<Cow<'static, str>> 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<String> for DebugName {
fn from(value: String) -> Self {
Self::owned(value)
impl From<String> for DebugName {
fn from(value: String) -> Self {
Self::owned(value)
}
}
}