Skip to content

Commit

Permalink
Remove Implicit std Prelude from no_std Crates (#17086)
Browse files Browse the repository at this point in the history
# Background

In `no_std` compatible crates, there is often an `std` feature which
will allow access to the standard library. Currently, with the `std`
feature _enabled_, the
[`std::prelude`](https://doc.rust-lang.org/std/prelude/index.html) is
implicitly imported in all modules. With the feature _disabled_, instead
the [`core::prelude`](https://doc.rust-lang.org/core/prelude/index.html)
is implicitly imported. This creates a subtle and pervasive issue where
`alloc` items _may_ be implicitly included (if `std` is enabled), or
must be explicitly included (if `std` is not enabled).

# Objective

- Make the implicit imports for `no_std` crates consistent regardless of
what features are/not enabled.

## Solution

- Replace the `cfg_attr` "double negative" `no_std` attribute with
conditional compilation to _include_ `std` as an external crate.
```rust
// Before
#![cfg_attr(not(feature = "std"), no_std)]

// After
#![no_std]

#[cfg(feature = "std")]
extern crate std;
```
- Fix imports that are currently broken but are only now visible with
the above fix.

## Testing

- CI

## Notes

I had previously used the "double negative" version of `no_std` based on
general consensus that it was "cleaner" within the Rust embedded
community. However, this implicit prelude issue likely was considered
when forming this consensus. I believe the reason why is the items most
affected by this issue are provided by the `alloc` crate, which is
rarely used within embedded but extensively used within Bevy.
  • Loading branch information
bushrat011899 authored Jan 3, 2025
1 parent 5a5ddb9 commit 0403948
Show file tree
Hide file tree
Showing 113 changed files with 267 additions and 102 deletions.
5 changes: 4 additions & 1 deletion crates/bevy_app/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@
html_logo_url = "https://bevyengine.org/assets/icon.png",
html_favicon_url = "https://bevyengine.org/assets/icon.png"
)]
#![cfg_attr(not(feature = "std"), no_std)]
#![no_std]

//! This crate is about everything concerning the highest-level, application layer of a Bevy app.
#[cfg(feature = "std")]
extern crate std;

extern crate alloc;

mod app;
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_app/src/plugin_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ impl PluginGroup for NoopPluginGroup {

#[cfg(test)]
mod tests {
use alloc::vec;
use core::{any::TypeId, fmt::Debug};

use super::PluginGroupBuilder;
Expand Down
5 changes: 4 additions & 1 deletion crates/bevy_color/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
html_logo_url = "https://bevyengine.org/assets/icon.png",
html_favicon_url = "https://bevyengine.org/assets/icon.png"
)]
#![cfg_attr(not(feature = "std"), no_std)]
#![no_std]

//! Representations of colors in various color spaces.
//!
Expand Down Expand Up @@ -90,6 +90,9 @@
//! println!("Hsla: {:?}", hsla);
//! ```
#[cfg(feature = "std")]
extern crate std;

#[cfg(feature = "alloc")]
extern crate alloc;

Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1643,6 +1643,7 @@ fn sorted_remove<T: Eq + Ord + Copy>(source: &mut Vec<T>, remove: &[T]) {
mod tests {
use crate as bevy_ecs;
use crate::{component::ComponentId, prelude::*, world::DeferredWorld};
use alloc::vec;

#[derive(Component)]
struct A;
Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_ecs/src/entity/clone_entities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,7 @@ mod tests {
entity::EntityCloneBuilder,
world::{DeferredWorld, World},
};
use alloc::vec::Vec;
use bevy_ecs_macros::require;
use bevy_ptr::OwningPtr;
use core::alloc::Layout;
Expand All @@ -679,6 +680,7 @@ mod tests {
mod reflect {
use super::*;
use crate::reflect::{AppTypeRegistry, ReflectComponent, ReflectFromWorld};
use alloc::vec;
use bevy_reflect::{std_traits::ReflectDefault, FromType, Reflect, ReflectFromPtr};

#[test]
Expand Down
3 changes: 3 additions & 0 deletions crates/bevy_ecs/src/entity/entity_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ unsafe impl<T: TrustedEntityBorrow> TrustedEntityBorrow for Arc<T> {}
/// [`into_iter()`]: IntoIterator::into_iter
/// [`iter_many_unique`]: crate::system::Query::iter_many_unique
/// [`iter_many_unique_mut`]: crate::system::Query::iter_many_unique_mut
/// [`Vec`]: alloc::vec::Vec
pub trait EntitySet: IntoIterator<IntoIter: EntitySetIterator> {}

impl<T: IntoIterator<IntoIter: EntitySetIterator>> EntitySet for T {}
Expand Down Expand Up @@ -379,6 +380,8 @@ impl<I: Iterator<Item: TrustedEntityBorrow> + Debug> Debug for UniqueEntityIter<

#[cfg(test)]
mod tests {
use alloc::{vec, vec::Vec};

#[allow(unused_imports)]
use crate::prelude::{Schedule, World};

Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_ecs/src/entity/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ use core::{fmt, hash::Hash, mem, num::NonZero};
use log::warn;

#[cfg(feature = "track_location")]
use core::panic::Location;
use {alloc::format, core::panic::Location};

#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -1065,6 +1065,7 @@ impl EntityLocation {
#[cfg(test)]
mod tests {
use super::*;
use alloc::format;

#[test]
fn entity_niche_optimization() {
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/src/entity/visit_entities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ mod tests {
entity::{EntityHashMap, MapEntities, SceneEntityMapper},
world::World,
};
use alloc::{string::String, vec, vec::Vec};
use bevy_utils::HashSet;

use super::*;
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/src/event/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub use writer::EventWriter;
#[cfg(test)]
mod tests {
use crate as bevy_ecs;
use alloc::{vec, vec::Vec};
use bevy_ecs::{event::*, system::assert_is_read_only_system};
use bevy_ecs_macros::Event;

Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/src/intern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ impl<T: ?Sized> Default for Interner<T> {

#[cfg(test)]
mod tests {
use alloc::{boxed::Box, string::ToString};
use bevy_utils::FixedHasher;
use core::hash::{BuildHasher, Hash, Hasher};

Expand Down
12 changes: 10 additions & 2 deletions crates/bevy_ecs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
html_logo_url = "https://bevyengine.org/assets/icon.png",
html_favicon_url = "https://bevyengine.org/assets/icon.png"
)]
#![cfg_attr(not(feature = "std"), no_std)]
#![no_std]

#[cfg(feature = "std")]
extern crate std;

#[cfg(target_pointer_width = "16")]
compile_error!("bevy_ecs cannot safely compile for a 16-bit platform.");
Expand Down Expand Up @@ -120,7 +123,12 @@ mod tests {
system::Resource,
world::{EntityMut, EntityRef, Mut, World},
};
use alloc::{sync::Arc, vec};
use alloc::{
string::{String, ToString},
sync::Arc,
vec,
vec::Vec,
};
use bevy_ecs_macros::{VisitEntities, VisitEntitiesMut};
use bevy_tasks::{ComputeTaskPool, TaskPool};
use bevy_utils::HashSet;
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ impl<'de> Visitor<'de> for NameVisitor {
mod tests {
use super::*;
use crate::world::World;
use alloc::string::ToString;

#[test]
fn test_display_of_debug_name() {
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/observer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@ impl World {

#[cfg(test)]
mod tests {
use alloc::vec;
use alloc::{vec, vec::Vec};

use bevy_ptr::OwningPtr;
use bevy_utils::HashMap;
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/src/query/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1338,6 +1338,7 @@ mod tests {
use crate::query::{
access::AccessFilters, Access, AccessConflicts, FilteredAccess, FilteredAccessSet,
};
use alloc::vec;
use core::marker::PhantomData;
use fixedbitset::FixedBitSet;

Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/src/query/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ impl<'w, D: QueryData, F: QueryFilter> QueryBuilder<'w, D, F> {
mod tests {
use crate as bevy_ecs;
use crate::{prelude::*, world::FilteredEntityRef};
use std::dbg;

#[derive(Component, PartialEq, Debug)]
struct A(usize);
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/src/query/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ pub enum QuerySingleError {
mod test {
use crate as bevy_ecs;
use crate::prelude::World;
use alloc::format;
use bevy_ecs_macros::Component;

#[test]
Expand Down
3 changes: 3 additions & 0 deletions crates/bevy_ecs/src/query/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2950,6 +2950,9 @@ impl<T> Ord for NeutralOrd<T> {

#[cfg(test)]
mod tests {
use alloc::vec::Vec;
use std::println;

#[allow(unused_imports)]
use crate::component::Component;
#[allow(unused_imports)]
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_ecs/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,10 @@ mod tests {
system::{assert_is_system, IntoSystem, Query, System, SystemState},
world::{unsafe_world_cell::UnsafeWorldCell, World},
};
use alloc::{vec, vec::Vec};
use bevy_ecs_macros::QueryFilter;
use core::{any::type_name, fmt::Debug, hash::Hash};
use std::collections::HashSet;
use std::{collections::HashSet, println};

#[derive(Component, Debug, Hash, Eq, PartialEq, Clone, Copy, PartialOrd, Ord)]
struct A(usize);
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/src/query/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1883,6 +1883,7 @@ mod tests {
use crate::{
component::Component, prelude::*, query::QueryEntityError, world::FilteredEntityRef,
};
use alloc::vec::Vec;

#[test]
fn get_many_unchecked_manual_uniqueness() {
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/src/reflect/entity_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ mod tests {
system::{Commands, SystemState},
world::World,
};
use alloc::{borrow::ToOwned, boxed::Box};
use bevy_ecs_macros::Resource;
use bevy_reflect::{PartialReflect, Reflect, TypeRegistry};

Expand Down
5 changes: 4 additions & 1 deletion crates/bevy_ecs/src/schedule/executor/multi_threaded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use bevy_utils::{default, syncunsafecell::SyncUnsafeCell};
use concurrent_queue::ConcurrentQueue;
use core::{any::Any, panic::AssertUnwindSafe};
use fixedbitset::FixedBitSet;
use std::sync::{Mutex, MutexGuard};
use std::{
eprintln,
sync::{Mutex, MutexGuard},
};

#[cfg(feature = "trace")]
use tracing::{info_span, Span};
Expand Down
4 changes: 4 additions & 0 deletions crates/bevy_ecs/src/schedule/executor/simple.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use core::panic::AssertUnwindSafe;
use fixedbitset::FixedBitSet;

#[cfg(feature = "trace")]
use tracing::info_span;

#[cfg(feature = "std")]
use std::eprintln;

use crate::{
schedule::{
executor::is_apply_deferred, BoxedCondition, ExecutorKind, SystemExecutor, SystemSchedule,
Expand Down
4 changes: 4 additions & 0 deletions crates/bevy_ecs/src/schedule/executor/single_threaded.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use core::panic::AssertUnwindSafe;
use fixedbitset::FixedBitSet;

#[cfg(feature = "trace")]
use tracing::info_span;

#[cfg(feature = "std")]
use std::eprintln;

use crate::{
schedule::{is_apply_deferred, BoxedCondition, ExecutorKind, SystemExecutor, SystemSchedule},
world::World,
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/src/schedule/graph/graph_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ impl CompactNodeIdPair {
#[cfg(test)]
mod tests {
use super::*;
use alloc::vec;

/// The `Graph` type _must_ preserve the order that nodes are inserted in if
/// no removals occur. Removals are permitted to swap the latest node into the
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/src/schedule/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub use self::graph::NodeId;
#[cfg(test)]
mod tests {
use super::*;
use alloc::{string::ToString, vec, vec::Vec};
use core::sync::atomic::{AtomicU32, Ordering};

pub use crate as bevy_ecs;
Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_ecs/src/schedule/stepping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,8 @@ impl ScheduleState {
mod tests {
use super::*;
use crate::{prelude::*, schedule::ScheduleLabel};
use alloc::{format, vec};
use std::println;

pub use crate as bevy_ecs;

Expand Down
8 changes: 8 additions & 0 deletions crates/bevy_ecs/src/storage/blob_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ impl BlobArray {
/// # Safety
/// - The element at index `index` is safe to access.
/// (If the safety requirements of every method that has been used on `Self` have been fulfilled, the caller just needs to ensure that `index` < `len`)
///
/// [`Vec::len`]: alloc::vec::Vec::len
#[inline]
pub unsafe fn get_unchecked(&self, index: usize) -> Ptr<'_> {
#[cfg(debug_assertions)]
Expand All @@ -98,6 +100,8 @@ impl BlobArray {
/// # Safety
/// - The element with at index `index` is safe to access.
/// (If the safety requirements of every method that has been used on `Self` have been fulfilled, the caller just needs to ensure that `index` < `len`)
///
/// [`Vec::len`]: alloc::vec::Vec::len
#[inline]
pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> PtrMut<'_> {
#[cfg(debug_assertions)]
Expand Down Expand Up @@ -134,6 +138,8 @@ impl BlobArray {
/// # Safety
/// - The type `T` must be the type of the items in this [`BlobArray`].
/// - `slice_len` <= `len`
///
/// [`Vec::len`]: alloc::vec::Vec::len
pub unsafe fn get_sub_slice<T>(&self, slice_len: usize) -> &[UnsafeCell<T>] {
#[cfg(debug_assertions)]
debug_assert!(slice_len <= self.capacity);
Expand All @@ -151,6 +157,8 @@ impl BlobArray {
/// # Safety
/// - For every element with index `i`, if `i` < `len`: It must be safe to call [`Self::get_unchecked_mut`] with `i`.
/// (If the safety requirements of every method that has been used on `Self` have been fulfilled, the caller just needs to ensure that `len` is correct.)
///
/// [`Vec::clear`]: alloc::vec::Vec::clear
pub unsafe fn clear(&mut self, len: usize) {
#[cfg(debug_assertions)]
debug_assert!(self.capacity >= len);
Expand Down
8 changes: 5 additions & 3 deletions crates/bevy_ecs/src/storage/blob_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,11 +497,13 @@ const fn padding_needed_for(layout: &Layout, align: usize) -> usize {

#[cfg(test)]
mod tests {
use super::BlobVec;
use crate as bevy_ecs; // required for derive macros
use crate::{component::Component, ptr::OwningPtr, world::World};

use super::BlobVec;
use alloc::rc::Rc;
use alloc::{
rc::Rc,
string::{String, ToString},
};
use core::{alloc::Layout, cell::RefCell};

/// # Safety
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/src/storage/sparse_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,7 @@ mod tests {
entity::Entity,
storage::SparseSet,
};
use alloc::{vec, vec::Vec};

#[derive(Debug, Eq, PartialEq)]
struct Foo(usize);
Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_ecs/src/storage/table/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,8 @@ mod tests {
ptr::OwningPtr,
storage::{Storages, TableBuilder, TableId, TableRow, Tables},
};
use alloc::vec::Vec;

#[cfg(feature = "track_location")]
use core::panic::Location;

Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_ecs/src/storage/thin_array_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ use core::{
///
/// This type can be treated as a `ManuallyDrop<Box<[T]>>` without a built in length. To avoid
/// memory leaks, [`drop`](Self::drop) must be called when no longer in use.
///
/// [`Vec<T>`]: alloc::vec::Vec
pub struct ThinArrayPtr<T> {
data: NonNull<T>,
#[cfg(debug_assertions)]
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/src/system/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,7 @@ mod tests {
prelude::{Component, Query},
system::{Local, RunSystemOnce},
};
use alloc::vec;

use super::*;

Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/system/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2284,7 +2284,7 @@ mod tests {
system::{Commands, Resource},
world::{CommandQueue, FromWorld, World},
};
use alloc::sync::Arc;
use alloc::{string::String, sync::Arc, vec, vec::Vec};
use core::{
any::TypeId,
sync::atomic::{AtomicUsize, Ordering},
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ecs/src/system/exclusive_system_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ all_tuples!(
mod tests {
use crate as bevy_ecs;
use crate::{schedule::Schedule, system::Local, world::World};
use alloc::vec::Vec;
use bevy_ecs_macros::Resource;
use core::marker::PhantomData;

Expand Down
Loading

0 comments on commit 0403948

Please sign in to comment.