From 5a988ac46e371cdabaa29dfcd9ccb69c0d47a47d Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Tue, 10 Dec 2024 21:45:08 +1100 Subject: [PATCH 1/4] Bare-minimum `no_std` Support --- crates/bevy_ecs/Cargo.toml | 82 +++++++++++--- crates/bevy_ecs/src/archetype.rs | 1 + crates/bevy_ecs/src/bundle.rs | 1 + crates/bevy_ecs/src/component.rs | 100 ++++++++++++------ crates/bevy_ecs/src/entity/clone_entities.rs | 8 +- crates/bevy_ecs/src/entity/mod.rs | 19 +++- crates/bevy_ecs/src/event/collections.rs | 8 +- crates/bevy_ecs/src/event/iterators.rs | 4 +- crates/bevy_ecs/src/event/mut_iterators.rs | 4 +- crates/bevy_ecs/src/event/registry.rs | 1 + crates/bevy_ecs/src/intern.rs | 40 ++++++- crates/bevy_ecs/src/lib.rs | 11 +- .../bevy_ecs/src/observer/entity_observer.rs | 1 + crates/bevy_ecs/src/observer/mod.rs | 1 + crates/bevy_ecs/src/observer/runner.rs | 1 + crates/bevy_ecs/src/observer/trigger_event.rs | 1 + crates/bevy_ecs/src/query/access.rs | 1 + crates/bevy_ecs/src/query/fetch.rs | 2 +- crates/bevy_ecs/src/query/iter.rs | 5 +- crates/bevy_ecs/src/query/state.rs | 15 +-- crates/bevy_ecs/src/reflect/bundle.rs | 1 + .../bevy_ecs/src/reflect/entity_commands.rs | 2 +- crates/bevy_ecs/src/reflect/from_world.rs | 1 + crates/bevy_ecs/src/result.rs | 2 + crates/bevy_ecs/src/schedule/condition.rs | 3 +- crates/bevy_ecs/src/schedule/config.rs | 1 + crates/bevy_ecs/src/schedule/executor/mod.rs | 25 +++-- .../src/schedule/executor/multi_threaded.rs | 8 +- .../bevy_ecs/src/schedule/executor/simple.rs | 23 ++-- .../src/schedule/executor/single_threaded.rs | 24 +++-- .../bevy_ecs/src/schedule/graph/graph_map.rs | 1 + crates/bevy_ecs/src/schedule/schedule.rs | 17 ++- crates/bevy_ecs/src/schedule/set.rs | 1 + crates/bevy_ecs/src/schedule/stepping.rs | 18 ++-- crates/bevy_ecs/src/storage/resource.rs | 18 ++++ crates/bevy_ecs/src/storage/sparse_set.rs | 1 + crates/bevy_ecs/src/storage/table/column.rs | 1 + crates/bevy_ecs/src/storage/table/mod.rs | 1 + crates/bevy_ecs/src/storage/thin_array_ptr.rs | 5 +- crates/bevy_ecs/src/system/adapter_system.rs | 2 +- crates/bevy_ecs/src/system/builder.rs | 1 + crates/bevy_ecs/src/system/combinator.rs | 2 +- crates/bevy_ecs/src/system/commands/mod.rs | 6 +- .../src/system/exclusive_function_system.rs | 2 +- crates/bevy_ecs/src/system/function_system.rs | 6 +- crates/bevy_ecs/src/system/mod.rs | 8 +- crates/bevy_ecs/src/system/schedule_system.rs | 2 +- crates/bevy_ecs/src/system/system.rs | 4 +- crates/bevy_ecs/src/system/system_param.rs | 1 + crates/bevy_ecs/src/system/system_registry.rs | 1 + crates/bevy_ecs/src/world/command_queue.rs | 63 ++++++----- crates/bevy_ecs/src/world/deferred_world.rs | 2 +- crates/bevy_ecs/src/world/entity_fetch.rs | 1 + crates/bevy_ecs/src/world/entity_ref.rs | 1 + .../bevy_ecs/src/world/filtered_resource.rs | 41 +++++-- crates/bevy_ecs/src/world/identifier.rs | 5 + crates/bevy_ecs/src/world/mod.rs | 19 ++-- crates/bevy_ecs/src/world/reflect.rs | 1 + .../bevy_ecs/src/world/unsafe_world_cell.rs | 8 +- crates/bevy_utils/Cargo.toml | 7 +- crates/bevy_utils/src/lib.rs | 6 ++ tools/ci/src/commands/compile_check_no_std.rs | 8 ++ 62 files changed, 475 insertions(+), 181 deletions(-) diff --git a/crates/bevy_ecs/Cargo.toml b/crates/bevy_ecs/Cargo.toml index 166c0178e463e..f7ac0e430e91b 100644 --- a/crates/bevy_ecs/Cargo.toml +++ b/crates/bevy_ecs/Cargo.toml @@ -11,27 +11,63 @@ categories = ["game-engines", "data-structures"] rust-version = "1.81.0" [features] -default = ["bevy_reflect"] -trace = [] +default = ["std", "bevy_reflect", "async_executor"] +std = [ + "bevy_reflect?/std", + "bevy_tasks/std", + "bevy_utils/std", + "bitflags/std", + "concurrent-queue/std", + "disqualified/alloc", + "fixedbitset/std", + "indexmap/std", + "serde?/std", + "nonmax/std", + "arrayvec?/std", + "log/std", +] +trace = ["std", "dep:tracing", "bevy_utils/tracing"] multi_threaded = ["bevy_tasks/multi_threaded", "arrayvec"] bevy_debug_stepping = [] -serialize = ["dep:serde"] +serialize = ["dep:serde", "bevy_utils/serde"] track_change_detection = [] reflect_functions = ["bevy_reflect", "bevy_reflect/functions"] -detailed_trace = [] +detailed_trace = ["trace"] +arrayvec = ["dep:arrayvec"] +async_executor = ["bevy_tasks/async_executor"] +edge_executor = ["bevy_tasks/edge_executor"] +critical-section = [ + "dep:critical-section", + "bevy_tasks/critical-section", + "portable-atomic?/critical-section", +] +portable-atomic = [ + "dep:portable-atomic", + "dep:portable-atomic-util", + "bevy_tasks/portable-atomic", + "concurrent-queue/portable-atomic", +] + [dependencies] bevy_ptr = { path = "../bevy_ptr", version = "0.15.0-dev" } -bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", optional = true } -bevy_tasks = { path = "../bevy_tasks", version = "0.15.0-dev" } -bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev" } +bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", default-features = false, features = [ + "smallvec", + "debug", +], optional = true } +bevy_tasks = { path = "../bevy_tasks", version = "0.15.0-dev", default-features = false } +bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev", default-features = false, features = [ + "alloc", +] } bevy_ecs_macros = { path = "macros", version = "0.15.0-dev" } -bitflags = "2.3" -concurrent-queue = "2.5.0" -disqualified = "1.0" -fixedbitset = "0.5" -serde = { version = "1", optional = true, default-features = false } +bitflags = { version = "2.3", default-features = false } +concurrent-queue = { version = "2.5.0", default-features = false } +disqualified = { version = "1.0", default-features = false } +fixedbitset = { version = "0.5", default-features = false } +serde = { version = "1", default-features = false, features = [ + "alloc", +], optional = true } thiserror = { version = "2", default-features = false } derive_more = { version = "1", default-features = false, features = [ "from", @@ -39,11 +75,25 @@ derive_more = { version = "1", default-features = false, features = [ "into", "as_ref", ] } -nonmax = "0.5" -arrayvec = { version = "0.7.4", optional = true } +nonmax = { version = "0.5", default-features = false } +arrayvec = { version = "0.7.4", default-features = false, optional = true } smallvec = { version = "1", features = ["union"] } -indexmap = { version = "2.5.0", default-features = false, features = ["std"] } -variadics_please = "1.0" +indexmap = { version = "2.5.0", default-features = false } +variadics_please = { version = "1.0", default-features = false } +critical-section = { version = "1.2.0", optional = true } +portable-atomic = { version = "1", default-features = false, features = [ + "fallback", +], optional = true } +portable-atomic-util = { version = "0.2.4", features = [ + "alloc", +], optional = true } +spin = { version = "0.9.8", default-features = false, features = [ + "spin_mutex", + "rwlock", + "once", +] } +tracing = { version = "0.1", default-features = false, optional = true } +log = { version = "0.4", default-features = false } [dev-dependencies] rand = "0.8" diff --git a/crates/bevy_ecs/src/archetype.rs b/crates/bevy_ecs/src/archetype.rs index 2c2241e29ec6d..af59bfa0d8d6a 100644 --- a/crates/bevy_ecs/src/archetype.rs +++ b/crates/bevy_ecs/src/archetype.rs @@ -26,6 +26,7 @@ use crate::{ observer::Observers, storage::{ImmutableSparseSet, SparseArray, SparseSet, SparseSetIndex, TableId, TableRow}, }; +use alloc::{boxed::Box, vec::Vec}; use bevy_utils::HashMap; use core::{ hash::Hash, diff --git a/crates/bevy_ecs/src/bundle.rs b/crates/bevy_ecs/src/bundle.rs index 333358240c23b..c72a31500e102 100644 --- a/crates/bevy_ecs/src/bundle.rs +++ b/crates/bevy_ecs/src/bundle.rs @@ -20,6 +20,7 @@ use crate::{ storage::{SparseSetIndex, SparseSets, Storages, Table, TableRow}, world::{unsafe_world_cell::UnsafeWorldCell, ON_ADD, ON_INSERT, ON_REPLACE}, }; +use alloc::{boxed::Box, vec, vec::Vec}; use bevy_ptr::{ConstNonNull, OwningPtr}; use bevy_utils::{HashMap, HashSet, TypeIdMap}; #[cfg(feature = "track_change_detection")] diff --git a/crates/bevy_ecs/src/component.rs b/crates/bevy_ecs/src/component.rs index 56e06315e5a4d..b1e6c25cbd46d 100644 --- a/crates/bevy_ecs/src/component.rs +++ b/crates/bevy_ecs/src/component.rs @@ -11,7 +11,7 @@ use crate::{ system::{Local, Resource, SystemParam}, world::{DeferredWorld, FromWorld, World}, }; -use alloc::{borrow::Cow, sync::Arc}; +use alloc::{borrow::Cow, vec::Vec}; pub use bevy_ecs_macros::Component; use bevy_ptr::{OwningPtr, UnsafeCellDeref}; #[cfg(feature = "bevy_reflect")] @@ -29,6 +29,12 @@ use core::{ }; use thiserror::Error; +#[cfg(feature = "portable-atomic")] +use portable_atomic_util::Arc; + +#[cfg(not(feature = "portable-atomic"))] +use alloc::sync::Arc; + pub use bevy_ecs_macros::require; /// A data type that can be used to store data for an [entity]. @@ -1983,35 +1989,69 @@ impl RequiredComponents { constructor: fn() -> C, inheritance_depth: u16, ) { - let erased: RequiredComponentConstructor = RequiredComponentConstructor(Arc::new( - move |table, - sparse_sets, - change_tick, - table_row, - entity, - #[cfg(feature = "track_change_detection")] caller| { - OwningPtr::make(constructor(), |ptr| { - // SAFETY: This will only be called in the context of `BundleInfo::write_components`, which will - // pass in a valid table_row and entity requiring a C constructor - // C::STORAGE_TYPE is the storage type associated with `component_id` / `C` - // `ptr` points to valid `C` data, which matches the type associated with `component_id` - unsafe { - BundleInfo::initialize_required_component( - table, - sparse_sets, - change_tick, - table_row, - entity, - component_id, - C::STORAGE_TYPE, - ptr, - #[cfg(feature = "track_change_detection")] - caller, - ); - } - }); - }, - )); + let erased: RequiredComponentConstructor = RequiredComponentConstructor({ + // `portable-atomic-util` `Arc` is not able to coerce an unsized + // type like `std::sync::Arc` can. Creating a `Box` first does the + // coercion. + // + // This would be resolved by https://github.com/rust-lang/rust/issues/123430 + + #[cfg(feature = "portable-atomic")] + use alloc::boxed::Box; + + #[cfg(feature = "track_change_detection")] + type Constructor = dyn for<'a, 'b> Fn( + &'a mut Table, + &'b mut SparseSets, + Tick, + TableRow, + Entity, + &'static Location<'static>, + ); + + #[cfg(not(feature = "track_change_detection"))] + type Constructor = + dyn for<'a, 'b> Fn(&'a mut Table, &'b mut SparseSets, Tick, TableRow, Entity); + + #[cfg(feature = "portable-atomic")] + type BoxedRequiredComponentConstructor = Box; + + #[cfg(not(feature = "portable-atomic"))] + type BoxedRequiredComponentConstructor = Arc; + + let boxed: BoxedRequiredComponentConstructor = Box::new( + move |table, + sparse_sets, + change_tick, + table_row, + entity, + #[cfg(feature = "track_change_detection")] caller| { + OwningPtr::make(constructor(), |ptr| { + // SAFETY: This will only be called in the context of `BundleInfo::write_components`, which will + // pass in a valid table_row and entity requiring a C constructor + // C::STORAGE_TYPE is the storage type associated with `component_id` / `C` + // `ptr` points to valid `C` data, which matches the type associated with `component_id` + unsafe { + BundleInfo::initialize_required_component( + table, + sparse_sets, + change_tick, + table_row, + entity, + component_id, + C::STORAGE_TYPE, + ptr, + #[cfg(feature = "track_change_detection")] + caller, + ); + } + }); + }, + ); + + Arc::from(boxed) + }); + // SAFETY: // `component_id` matches the type initialized by the `erased` constructor above. // `erased` initializes a component for `component_id` in such a way that diff --git a/crates/bevy_ecs/src/entity/clone_entities.rs b/crates/bevy_ecs/src/entity/clone_entities.rs index da0e51c25fcf6..57b05a1cbfffa 100644 --- a/crates/bevy_ecs/src/entity/clone_entities.rs +++ b/crates/bevy_ecs/src/entity/clone_entities.rs @@ -1,8 +1,14 @@ -use alloc::sync::Arc; +use alloc::vec::Vec; use core::any::TypeId; use bevy_utils::{HashMap, HashSet}; +#[cfg(feature = "portable-atomic")] +use portable_atomic_util::Arc; + +#[cfg(not(feature = "portable-atomic"))] +use alloc::sync::Arc; + use crate::{ bundle::Bundle, component::{component_clone_ignore, Component, ComponentCloneHandler, ComponentId}, diff --git a/crates/bevy_ecs/src/entity/mod.rs b/crates/bevy_ecs/src/entity/mod.rs index 68a89f660f2e4..2b27c7fed63ea 100644 --- a/crates/bevy_ecs/src/entity/mod.rs +++ b/crates/bevy_ecs/src/entity/mod.rs @@ -49,7 +49,8 @@ pub use visit_entities::*; mod hash; pub use hash::*; -use bevy_utils::tracing::warn; +use alloc::vec::Vec; +use log::warn; use crate::{ archetype::{ArchetypeId, ArchetypeRow}, @@ -61,20 +62,30 @@ use crate::{ }, storage::{SparseSetIndex, TableId, TableRow}, }; -use core::{fmt, hash::Hash, mem, num::NonZero, sync::atomic::Ordering}; +use core::{fmt, hash::Hash, mem, num::NonZero}; #[cfg(feature = "serialize")] use serde::{Deserialize, Serialize}; -#[cfg(target_has_atomic = "64")] +#[cfg(not(feature = "portable-atomic"))] +use core::sync::atomic::Ordering; + +#[cfg(feature = "portable-atomic")] +use portable_atomic::Ordering; + +#[cfg(all(target_has_atomic = "64", not(feature = "portable-atomic")))] use core::sync::atomic::AtomicI64 as AtomicIdCursor; +#[cfg(all(target_has_atomic = "64", feature = "portable-atomic"))] +use portable_atomic::AtomicI64 as AtomicIdCursor; #[cfg(target_has_atomic = "64")] type IdCursor = i64; /// Most modern platforms support 64-bit atomics, but some less-common platforms /// do not. This fallback allows compilation using a 32-bit cursor instead, with /// the caveat that some conversions may fail (and panic) at runtime. -#[cfg(not(target_has_atomic = "64"))] +#[cfg(all(not(target_has_atomic = "64"), not(feature = "portable-atomic")))] use core::sync::atomic::AtomicIsize as AtomicIdCursor; +#[cfg(all(not(target_has_atomic = "64"), feature = "portable-atomic"))] +use portable_atomic::AtomicIsize as AtomicIdCursor; #[cfg(not(target_has_atomic = "64"))] type IdCursor = isize; diff --git a/crates/bevy_ecs/src/event/collections.rs b/crates/bevy_ecs/src/event/collections.rs index c04512ba62bba..b0f2253d432af 100644 --- a/crates/bevy_ecs/src/event/collections.rs +++ b/crates/bevy_ecs/src/event/collections.rs @@ -1,9 +1,9 @@ use crate as bevy_ecs; +use alloc::vec::Vec; use bevy_ecs::{ event::{Event, EventCursor, EventId, EventInstance}, system::Resource, }; -use bevy_utils::detailed_trace; use core::{ marker::PhantomData, ops::{Deref, DerefMut}, @@ -125,7 +125,8 @@ impl Events { id: self.event_count, _marker: PhantomData, }; - detailed_trace!("Events::send() -> id: {}", event_id); + #[cfg(feature = "detailed_trace")] + tracing::trace!("Events::send() -> id: {}", event_id); let event_instance = EventInstance { event_id, event }; @@ -318,7 +319,8 @@ impl Extend for Events { self.events_b.extend(events); if old_count != event_count { - detailed_trace!( + #[cfg(feature = "detailed_trace")] + tracing::trace!( "Events::extend() -> ids: ({}..{})", self.event_count, event_count diff --git a/crates/bevy_ecs/src/event/iterators.rs b/crates/bevy_ecs/src/event/iterators.rs index 28c671fe947db..956072715c74a 100644 --- a/crates/bevy_ecs/src/event/iterators.rs +++ b/crates/bevy_ecs/src/event/iterators.rs @@ -2,7 +2,6 @@ use crate as bevy_ecs; #[cfg(feature = "multi_threaded")] use bevy_ecs::batching::BatchingStrategy; use bevy_ecs::event::{Event, EventCursor, EventId, EventInstance, Events}; -use bevy_utils::detailed_trace; use core::{iter::Chain, slice::Iter}; /// An iterator that yields any unread events from an [`EventReader`](super::EventReader) or [`EventCursor`]. @@ -92,7 +91,8 @@ impl<'a, E: Event> Iterator for EventIteratorWithId<'a, E> { .map(|instance| (&instance.event, instance.event_id)) { Some(item) => { - detailed_trace!("EventReader::iter() -> {}", item.1); + #[cfg(feature = "detailed_trace")] + tracing::trace!("EventReader::iter() -> {}", item.1); self.reader.last_event_count += 1; self.unread -= 1; Some(item) diff --git a/crates/bevy_ecs/src/event/mut_iterators.rs b/crates/bevy_ecs/src/event/mut_iterators.rs index 5f70875a31702..f8f32236ea8e6 100644 --- a/crates/bevy_ecs/src/event/mut_iterators.rs +++ b/crates/bevy_ecs/src/event/mut_iterators.rs @@ -2,7 +2,6 @@ use crate as bevy_ecs; #[cfg(feature = "multi_threaded")] use bevy_ecs::batching::BatchingStrategy; use bevy_ecs::event::{Event, EventCursor, EventId, EventInstance, Events}; -use bevy_utils::detailed_trace; use core::{iter::Chain, slice::IterMut}; /// An iterator that yields any unread events from an [`EventMutator`] or [`EventCursor`]. @@ -95,7 +94,8 @@ impl<'a, E: Event> Iterator for EventMutIteratorWithId<'a, E> { .map(|instance| (&mut instance.event, instance.event_id)) { Some(item) => { - detailed_trace!("EventMutator::iter() -> {}", item.1); + #[cfg(feature = "detailed_trace")] + tracing::trace!("EventMutator::iter() -> {}", item.1); self.mutator.last_event_count += 1; self.unread -= 1; Some(item) diff --git a/crates/bevy_ecs/src/event/registry.rs b/crates/bevy_ecs/src/event/registry.rs index ccc7b9fb92a3f..3f92c1134a4cf 100644 --- a/crates/bevy_ecs/src/event/registry.rs +++ b/crates/bevy_ecs/src/event/registry.rs @@ -1,4 +1,5 @@ use crate as bevy_ecs; +use alloc::vec::Vec; use bevy_ecs::{ change_detection::{DetectChangesMut, MutUntyped}, component::{ComponentId, Tick}, diff --git a/crates/bevy_ecs/src/intern.rs b/crates/bevy_ecs/src/intern.rs index 179fdc8b82ad9..347f044669d9f 100644 --- a/crates/bevy_ecs/src/intern.rs +++ b/crates/bevy_ecs/src/intern.rs @@ -4,9 +4,15 @@ //! speed up code by shrinking the stack size of large types, //! and make comparisons for any type as fast as integers. +use alloc::{borrow::ToOwned, boxed::Box}; use core::{fmt::Debug, hash::Hash, ops::Deref}; + +#[cfg(feature = "std")] use std::sync::{OnceLock, PoisonError, RwLock}; +#[cfg(not(feature = "std"))] +use spin::{once::Once as OnceLock, rwlock::RwLock}; + use bevy_utils::HashSet; /// An interned value. Will stay valid until the end of the program and will not drop. @@ -136,15 +142,43 @@ impl Interner { /// [`Interned`] using the obtained static reference. Subsequent calls for the same `value` /// will return [`Interned`] using the same static reference. pub fn intern(&self, value: &T) -> Interned { - let lock = self.0.get_or_init(Default::default); + let lock = { + #[cfg(feature = "std")] + let lock = self.0.get_or_init(Default::default); + + #[cfg(not(feature = "std"))] + let lock = self.0.call_once(Default::default); + + lock + }; + { - let set = lock.read().unwrap_or_else(PoisonError::into_inner); + let set = { + #[cfg(feature = "std")] + let set = lock.read().unwrap_or_else(PoisonError::into_inner); + + #[cfg(not(feature = "std"))] + let set = lock.read(); + + set + }; + if let Some(value) = set.get(value) { return Interned(*value); } } + { - let mut set = lock.write().unwrap_or_else(PoisonError::into_inner); + let mut set = { + #[cfg(feature = "std")] + let set = lock.write().unwrap_or_else(PoisonError::into_inner); + + #[cfg(not(feature = "std"))] + let set = lock.write(); + + set + }; + if let Some(value) = set.get(value) { Interned(*value) } else { diff --git a/crates/bevy_ecs/src/lib.rs b/crates/bevy_ecs/src/lib.rs index 85ff83c0aade0..9d5fb3fff7d61 100644 --- a/crates/bevy_ecs/src/lib.rs +++ b/crates/bevy_ecs/src/lib.rs @@ -11,6 +11,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)] #[cfg(target_pointer_width = "16")] compile_error!("bevy_ecs cannot safely compile for a 16-bit platform."); @@ -63,9 +64,9 @@ pub mod prelude { }, system::{ Commands, Deferred, EntityCommand, EntityCommands, In, InMut, InRef, IntoSystem, Local, - NonSend, NonSendMut, ParallelCommands, ParamSet, Populated, Query, ReadOnlySystem, Res, - ResMut, Resource, Single, System, SystemIn, SystemInput, SystemParamBuilder, - SystemParamFunction, WithParamWarnPolicy, + NonSend, NonSendMut, ParamSet, Populated, Query, ReadOnlySystem, Res, ResMut, Resource, + Single, System, SystemIn, SystemInput, SystemParamBuilder, SystemParamFunction, + WithParamWarnPolicy, }, world::{ Command, EntityMut, EntityRef, EntityWorldMut, FilteredResources, FilteredResourcesMut, @@ -73,6 +74,10 @@ pub mod prelude { }, }; + #[doc(hidden)] + #[cfg(feature = "std")] + pub use crate::system::ParallelCommands; + #[doc(hidden)] #[cfg(feature = "bevy_reflect")] pub use crate::reflect::{ diff --git a/crates/bevy_ecs/src/observer/entity_observer.rs b/crates/bevy_ecs/src/observer/entity_observer.rs index 6fd39a4b42546..68b5bdc0e0ed6 100644 --- a/crates/bevy_ecs/src/observer/entity_observer.rs +++ b/crates/bevy_ecs/src/observer/entity_observer.rs @@ -4,6 +4,7 @@ use crate::{ observer::ObserverState, world::{DeferredWorld, World}, }; +use alloc::vec::Vec; /// Tracks a list of entity observers for the [`Entity`] [`ObservedBy`] is added to. #[derive(Default)] diff --git a/crates/bevy_ecs/src/observer/mod.rs b/crates/bevy_ecs/src/observer/mod.rs index 0cbb1b80b263e..c78484c6a6ff5 100644 --- a/crates/bevy_ecs/src/observer/mod.rs +++ b/crates/bevy_ecs/src/observer/mod.rs @@ -17,6 +17,7 @@ use crate::{ system::IntoObserverSystem, world::{DeferredWorld, *}, }; +use alloc::vec::Vec; use bevy_ptr::Ptr; use bevy_utils::HashMap; use core::{ diff --git a/crates/bevy_ecs/src/observer/runner.rs b/crates/bevy_ecs/src/observer/runner.rs index f7ee95972d435..b63f4f34a5d00 100644 --- a/crates/bevy_ecs/src/observer/runner.rs +++ b/crates/bevy_ecs/src/observer/runner.rs @@ -1,3 +1,4 @@ +use alloc::{boxed::Box, vec, vec::Vec}; use core::any::Any; use crate::{ diff --git a/crates/bevy_ecs/src/observer/trigger_event.rs b/crates/bevy_ecs/src/observer/trigger_event.rs index 5221aff070e2e..bf84e57bae301 100644 --- a/crates/bevy_ecs/src/observer/trigger_event.rs +++ b/crates/bevy_ecs/src/observer/trigger_event.rs @@ -4,6 +4,7 @@ use crate::{ event::Event, world::{Command, DeferredWorld, World}, }; +use alloc::vec::Vec; /// A [`Command`] that emits a given trigger for a given set of targets. pub struct TriggerEvent { diff --git a/crates/bevy_ecs/src/query/access.rs b/crates/bevy_ecs/src/query/access.rs index a0e311ab3dd5f..01e51dc6b6981 100644 --- a/crates/bevy_ecs/src/query/access.rs +++ b/crates/bevy_ecs/src/query/access.rs @@ -1,6 +1,7 @@ use crate::component::ComponentId; use crate::storage::SparseSetIndex; use crate::world::World; +use alloc::{format, string::String, vec, vec::Vec}; use core::{fmt, fmt::Debug, marker::PhantomData}; use derive_more::derive::From; use disqualified::ShortName; diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index a56754d95b8f8..13ad4655b895d 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -2366,7 +2366,7 @@ impl StorageSwitch { #[cfg(debug_assertions)] unreachable!(); #[cfg(not(debug_assertions))] - std::hint::unreachable_unchecked() + core::hint::unreachable_unchecked() } } } diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index 4de38258e9edc..9bd1f51483205 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -1,3 +1,4 @@ +use super::{QueryData, QueryFilter, ReadOnlyQueryData}; use crate::{ archetype::{Archetype, ArchetypeEntity, Archetypes}, component::Tick, @@ -6,6 +7,7 @@ use crate::{ storage::{Table, TableRow, Tables}, world::unsafe_world_cell::UnsafeWorldCell, }; +use alloc::vec::{IntoIter, Vec}; use core::{ borrow::Borrow, cmp::Ordering, @@ -15,9 +17,6 @@ use core::{ ops::Range, }; -use super::{QueryData, QueryFilter, ReadOnlyQueryData}; -use alloc::vec::IntoIter; - /// An [`Iterator`] over query results of a [`Query`](crate::system::Query). /// /// This struct is created by the [`Query::iter`](crate::system::Query::iter) and diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index f493ba7c97ef9..9c404f970f43f 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -11,11 +11,12 @@ use crate::{ storage::{SparseSetIndex, TableId}, world::{unsafe_world_cell::UnsafeWorldCell, World, WorldId}, }; -use bevy_utils::tracing::warn; -#[cfg(feature = "trace")] -use bevy_utils::tracing::Span; +use alloc::vec::Vec; use core::{borrow::Borrow, fmt, mem::MaybeUninit, ptr}; use fixedbitset::FixedBitSet; +use log::warn; +#[cfg(feature = "trace")] +use tracing::Span; use super::{ NopWorldQuery, QueryBuilder, QueryData, QueryEntityError, QueryFilter, QueryManyIter, @@ -251,7 +252,7 @@ impl QueryState { matched_tables: Default::default(), matched_archetypes: Default::default(), #[cfg(feature = "trace")] - par_iter_span: bevy_utils::tracing::info_span!( + par_iter_span: tracing::info_span!( "par_for_each", query = core::any::type_name::(), filter = core::any::type_name::(), @@ -277,7 +278,7 @@ impl QueryState { matched_tables: Default::default(), matched_archetypes: Default::default(), #[cfg(feature = "trace")] - par_iter_span: bevy_utils::tracing::info_span!( + par_iter_span: tracing::info_span!( "par_for_each", data = core::any::type_name::(), filter = core::any::type_name::(), @@ -640,7 +641,7 @@ impl QueryState { matched_tables: self.matched_tables.clone(), matched_archetypes: self.matched_archetypes.clone(), #[cfg(feature = "trace")] - par_iter_span: bevy_utils::tracing::info_span!( + par_iter_span: tracing::info_span!( "par_for_each", query = core::any::type_name::(), filter = core::any::type_name::(), @@ -762,7 +763,7 @@ impl QueryState { matched_tables, matched_archetypes, #[cfg(feature = "trace")] - par_iter_span: bevy_utils::tracing::info_span!( + par_iter_span: tracing::info_span!( "par_for_each", query = core::any::type_name::(), filter = core::any::type_name::(), diff --git a/crates/bevy_ecs/src/reflect/bundle.rs b/crates/bevy_ecs/src/reflect/bundle.rs index d5d52c734964c..248ca1a7048c1 100644 --- a/crates/bevy_ecs/src/reflect/bundle.rs +++ b/crates/bevy_ecs/src/reflect/bundle.rs @@ -4,6 +4,7 @@ //! This module exports two types: [`ReflectBundleFns`] and [`ReflectBundle`]. //! //! Same as [`super::component`], but for bundles. +use alloc::boxed::Box; use core::any::{Any, TypeId}; use crate::{ diff --git a/crates/bevy_ecs/src/reflect/entity_commands.rs b/crates/bevy_ecs/src/reflect/entity_commands.rs index 60c89c7f7f9ff..6ec1ba9b5ba17 100644 --- a/crates/bevy_ecs/src/reflect/entity_commands.rs +++ b/crates/bevy_ecs/src/reflect/entity_commands.rs @@ -5,7 +5,7 @@ use crate::{ system::{EntityCommands, Resource}, world::{Command, World}, }; -use alloc::borrow::Cow; +use alloc::{borrow::Cow, boxed::Box}; use bevy_reflect::{PartialReflect, TypeRegistry}; use core::marker::PhantomData; diff --git a/crates/bevy_ecs/src/reflect/from_world.rs b/crates/bevy_ecs/src/reflect/from_world.rs index fb9ffc8939ccd..c4f5912ff4b5f 100644 --- a/crates/bevy_ecs/src/reflect/from_world.rs +++ b/crates/bevy_ecs/src/reflect/from_world.rs @@ -6,6 +6,7 @@ //! //! Same as [`super::component`], but for [`FromWorld`]. +use alloc::boxed::Box; use bevy_reflect::{FromType, Reflect}; use crate::world::{FromWorld, World}; diff --git a/crates/bevy_ecs/src/result.rs b/crates/bevy_ecs/src/result.rs index 4127e2ec91d16..77e7fc00743ae 100644 --- a/crates/bevy_ecs/src/result.rs +++ b/crates/bevy_ecs/src/result.rs @@ -1,5 +1,7 @@ //! Contains error and result helpers for use in fallible systems. +use alloc::boxed::Box; + /// A dynamic error type for use in fallible systems. pub type Error = Box; diff --git a/crates/bevy_ecs/src/schedule/condition.rs b/crates/bevy_ecs/src/schedule/condition.rs index 6956d2715069f..c3f98198350bc 100644 --- a/crates/bevy_ecs/src/schedule/condition.rs +++ b/crates/bevy_ecs/src/schedule/condition.rs @@ -1,4 +1,4 @@ -use alloc::borrow::Cow; +use alloc::{borrow::Cow, boxed::Box, format}; use core::ops::Not; use crate::system::{ @@ -499,6 +499,7 @@ pub mod common_conditions { removal_detection::RemovedComponents, system::{In, IntoSystem, Local, Res, Resource, System, SystemInput}, }; + use alloc::format; /// A [`Condition`]-satisfying system that returns `true` /// on the first time the condition is run and false every time after. diff --git a/crates/bevy_ecs/src/schedule/config.rs b/crates/bevy_ecs/src/schedule/config.rs index 88bf0ffc8c591..a4518c0255773 100644 --- a/crates/bevy_ecs/src/schedule/config.rs +++ b/crates/bevy_ecs/src/schedule/config.rs @@ -1,3 +1,4 @@ +use alloc::{boxed::Box, vec, vec::Vec}; use variadics_please::all_tuples; use crate::{ diff --git a/crates/bevy_ecs/src/schedule/executor/mod.rs b/crates/bevy_ecs/src/schedule/executor/mod.rs index d0231bb2f0c5b..59aa86c522ba0 100644 --- a/crates/bevy_ecs/src/schedule/executor/mod.rs +++ b/crates/bevy_ecs/src/schedule/executor/mod.rs @@ -1,15 +1,15 @@ +#[cfg(feature = "std")] mod multi_threaded; mod simple; mod single_threaded; -use alloc::borrow::Cow; +use alloc::{borrow::Cow, vec, vec::Vec}; use core::any::TypeId; -pub use self::{ - multi_threaded::{MainThreadExecutor, MultiThreadedExecutor}, - simple::SimpleExecutor, - single_threaded::SingleThreadedExecutor, -}; +pub use self::{simple::SimpleExecutor, single_threaded::SingleThreadedExecutor}; + +#[cfg(feature = "std")] +pub use self::multi_threaded::{MainThreadExecutor, MultiThreadedExecutor}; use fixedbitset::FixedBitSet; @@ -53,6 +53,7 @@ pub enum ExecutorKind { /// immediately after running each system. Simple, /// Runs the schedule using a thread pool. Non-conflicting systems can run in parallel. + #[cfg(feature = "std")] #[cfg_attr(all(not(target_arch = "wasm32"), feature = "multi_threaded"), default)] MultiThreaded, } @@ -72,9 +73,17 @@ pub struct SystemSchedule { pub(super) system_conditions: Vec>, /// Indexed by system node id. /// Number of systems that the system immediately depends on. + #[cfg_attr( + not(feature = "std"), + expect(dead_code, reason = "currently only used with the std feature") + )] pub(super) system_dependencies: Vec, /// Indexed by system node id. /// List of systems that immediately depend on the system. + #[cfg_attr( + not(feature = "std"), + expect(dead_code, reason = "currently only used with the std feature") + )] pub(super) system_dependents: Vec>, /// Indexed by system node id. /// List of sets containing the system that have conditions @@ -262,6 +271,10 @@ mod __rust_begin_short_backtrace { /// # Safety /// See `ReadOnlySystem::run_unsafe`. + #[cfg_attr( + not(feature = "std"), + expect(dead_code, reason = "currently only used with the std feature") + )] #[inline(never)] pub(super) unsafe fn readonly_run_unsafe( system: &mut dyn ReadOnlySystem, diff --git a/crates/bevy_ecs/src/schedule/executor/multi_threaded.rs b/crates/bevy_ecs/src/schedule/executor/multi_threaded.rs index 8ee9c3575b018..2d85a79ec53bc 100644 --- a/crates/bevy_ecs/src/schedule/executor/multi_threaded.rs +++ b/crates/bevy_ecs/src/schedule/executor/multi_threaded.rs @@ -1,14 +1,12 @@ -use alloc::sync::Arc; +use alloc::{boxed::Box, sync::Arc, vec::Vec}; use core::any::Any; use std::sync::{Mutex, MutexGuard}; use bevy_tasks::{ComputeTaskPool, Scope, TaskPool, ThreadExecutor}; -#[cfg(feature = "trace")] -use bevy_utils::tracing::info_span; -#[cfg(feature = "trace")] -use bevy_utils::tracing::Span; use bevy_utils::{default, syncunsafecell::SyncUnsafeCell}; use core::panic::AssertUnwindSafe; +#[cfg(feature = "trace")] +use tracing::{info_span, Span}; use concurrent_queue::ConcurrentQueue; use fixedbitset::FixedBitSet; diff --git a/crates/bevy_ecs/src/schedule/executor/simple.rs b/crates/bevy_ecs/src/schedule/executor/simple.rs index fa3ccffb0b74d..5cf03e2088276 100644 --- a/crates/bevy_ecs/src/schedule/executor/simple.rs +++ b/crates/bevy_ecs/src/schedule/executor/simple.rs @@ -1,7 +1,7 @@ -#[cfg(feature = "trace")] -use bevy_utils::tracing::info_span; use core::panic::AssertUnwindSafe; use fixedbitset::FixedBitSet; +#[cfg(feature = "trace")] +use tracing::info_span; use crate::{ schedule::{ @@ -100,13 +100,22 @@ impl SystemExecutor for SimpleExecutor { continue; } - let res = std::panic::catch_unwind(AssertUnwindSafe(|| { + let f = AssertUnwindSafe(|| { // TODO: implement an error-handling API instead of suppressing a possible failure. let _ = __rust_begin_short_backtrace::run(system, world); - })); - if let Err(payload) = res { - eprintln!("Encountered a panic in system `{}`!", &*system.name()); - std::panic::resume_unwind(payload); + }); + + #[cfg(feature = "std")] + { + if let Err(payload) = std::panic::catch_unwind(f) { + eprintln!("Encountered a panic in system `{}`!", &*system.name()); + std::panic::resume_unwind(payload); + } + } + + #[cfg(not(feature = "std"))] + { + (f)(); } } diff --git a/crates/bevy_ecs/src/schedule/executor/single_threaded.rs b/crates/bevy_ecs/src/schedule/executor/single_threaded.rs index cd44c4e66eb17..d19a222d3011b 100644 --- a/crates/bevy_ecs/src/schedule/executor/single_threaded.rs +++ b/crates/bevy_ecs/src/schedule/executor/single_threaded.rs @@ -1,7 +1,7 @@ -#[cfg(feature = "trace")] -use bevy_utils::tracing::info_span; use core::panic::AssertUnwindSafe; use fixedbitset::FixedBitSet; +#[cfg(feature = "trace")] +use tracing::info_span; use crate::{ schedule::{is_apply_deferred, BoxedCondition, ExecutorKind, SystemExecutor, SystemSchedule}, @@ -107,7 +107,7 @@ impl SystemExecutor for SingleThreadedExecutor { continue; } - let res = std::panic::catch_unwind(AssertUnwindSafe(|| { + let f = AssertUnwindSafe(|| { if system.is_exclusive() { // TODO: implement an error-handling API instead of suppressing a possible failure. let _ = __rust_begin_short_backtrace::run(system, world); @@ -122,11 +122,21 @@ impl SystemExecutor for SingleThreadedExecutor { let _ = __rust_begin_short_backtrace::run_unsafe(system, world); }; } - })); - if let Err(payload) = res { - eprintln!("Encountered a panic in system `{}`!", &*system.name()); - std::panic::resume_unwind(payload); + }); + + #[cfg(feature = "std")] + { + if let Err(payload) = std::panic::catch_unwind(f) { + eprintln!("Encountered a panic in system `{}`!", &*system.name()); + std::panic::resume_unwind(payload); + } } + + #[cfg(not(feature = "std"))] + { + (f)(); + } + self.unapplied_systems.insert(system_index); } diff --git a/crates/bevy_ecs/src/schedule/graph/graph_map.rs b/crates/bevy_ecs/src/schedule/graph/graph_map.rs index 680774bce5f4d..24c4a6952be5a 100644 --- a/crates/bevy_ecs/src/schedule/graph/graph_map.rs +++ b/crates/bevy_ecs/src/schedule/graph/graph_map.rs @@ -4,6 +4,7 @@ //! //! [`petgraph`]: https://docs.rs/petgraph/0.6.5/petgraph/ +use alloc::vec::Vec; use bevy_utils::{hashbrown::HashSet, AHasher}; use core::{ fmt, diff --git a/crates/bevy_ecs/src/schedule/schedule.rs b/crates/bevy_ecs/src/schedule/schedule.rs index 449b609a28ff0..403de81ae0aed 100644 --- a/crates/bevy_ecs/src/schedule/schedule.rs +++ b/crates/bevy_ecs/src/schedule/schedule.rs @@ -1,17 +1,15 @@ -use alloc::collections::BTreeSet; +use alloc::{ + boxed::Box, collections::BTreeSet, format, string::String, string::ToString, vec, vec::Vec, +}; +use bevy_utils::{default, AHasher, HashMap, HashSet}; use core::fmt::{Debug, Write}; use core::hash::BuildHasherDefault; - -#[cfg(feature = "trace")] -use bevy_utils::tracing::info_span; -use bevy_utils::{ - default, - tracing::{error, info, warn}, - AHasher, HashMap, HashSet, -}; use disqualified::ShortName; use fixedbitset::FixedBitSet; +use log::{error, info, warn}; use thiserror::Error; +#[cfg(feature = "trace")] +use tracing::info_span; use crate::{ self as bevy_ecs, @@ -206,6 +204,7 @@ fn make_executor(kind: ExecutorKind) -> Box { match kind { ExecutorKind::Simple => Box::new(SimpleExecutor::new()), ExecutorKind::SingleThreaded => Box::new(SingleThreadedExecutor::new()), + #[cfg(feature = "std")] ExecutorKind::MultiThreaded => Box::new(MultiThreadedExecutor::new()), } } diff --git a/crates/bevy_ecs/src/schedule/set.rs b/crates/bevy_ecs/src/schedule/set.rs index 244dd436351ec..cbe1011e782a2 100644 --- a/crates/bevy_ecs/src/schedule/set.rs +++ b/crates/bevy_ecs/src/schedule/set.rs @@ -1,3 +1,4 @@ +use alloc::boxed::Box; use core::{ any::TypeId, fmt::Debug, diff --git a/crates/bevy_ecs/src/schedule/stepping.rs b/crates/bevy_ecs/src/schedule/stepping.rs index 9c607f6ce0662..ed796c29e9e4e 100644 --- a/crates/bevy_ecs/src/schedule/stepping.rs +++ b/crates/bevy_ecs/src/schedule/stepping.rs @@ -1,22 +1,19 @@ -use core::any::TypeId; -use fixedbitset::FixedBitSet; -use std::collections::HashMap; - use crate::{ schedule::{InternedScheduleLabel, NodeId, Schedule, ScheduleLabel}, system::{IntoSystem, ResMut, Resource, System}, }; -use bevy_utils::{ - tracing::{info, warn}, - TypeIdMap, -}; +use alloc::vec::Vec; +use bevy_utils::{HashMap, TypeIdMap}; +use core::any::TypeId; +use fixedbitset::FixedBitSet; +use log::{info, warn}; use thiserror::Error; #[cfg(not(feature = "bevy_debug_stepping"))] -use bevy_utils::tracing::error; +use log::error; #[cfg(test)] -use bevy_utils::tracing::debug; +use log::debug; use crate as bevy_ecs; @@ -423,6 +420,7 @@ impl Stepping { // transitions, and add debugging messages for permitted // transitions. Any action transition that falls through // this match block will be performed. + #[expect(clippy::match_same_arms)] match (self.action, action) { // ignore non-transition updates, and prevent a call to // enable() from overwriting a step or continue call diff --git a/crates/bevy_ecs/src/storage/resource.rs b/crates/bevy_ecs/src/storage/resource.rs index ed8700e1c74e2..76f14b3e10ef2 100644 --- a/crates/bevy_ecs/src/storage/resource.rs +++ b/crates/bevy_ecs/src/storage/resource.rs @@ -4,10 +4,13 @@ use crate::{ component::{ComponentId, ComponentTicks, Components, Tick, TickCells}, storage::{blob_vec::BlobVec, SparseSet}, }; +use alloc::string::String; use bevy_ptr::{OwningPtr, Ptr, UnsafeCellDeref}; #[cfg(feature = "track_change_detection")] use core::panic::Location; use core::{cell::UnsafeCell, mem::ManuallyDrop}; + +#[cfg(feature = "std")] use std::thread::ThreadId; /// The type-erased backing storage and metadata for a single resource within a [`World`]. @@ -19,8 +22,13 @@ pub struct ResourceData { data: ManuallyDrop, added_ticks: UnsafeCell, changed_ticks: UnsafeCell, + #[cfg_attr( + not(feature = "std"), + expect(dead_code, reason = "currently only used with the std feature") + )] type_name: String, id: ArchetypeComponentId, + #[cfg(feature = "std")] origin_thread_id: Option, #[cfg(feature = "track_change_detection")] changed_by: UnsafeCell<&'static Location<'static>>, @@ -35,6 +43,7 @@ impl Drop for ResourceData { // If this thread is already panicking, panicking again will cause // the entire process to abort. In this case we choose to avoid // dropping or checking this altogether and just leak the column. + #[cfg(feature = "std")] if std::thread::panicking() { return; } @@ -63,6 +72,8 @@ impl ResourceData { if SEND { return; } + + #[cfg(feature = "std")] if self.origin_thread_id != Some(std::thread::current().id()) { // Panic in tests, as testing for aborting is nearly impossible panic!( @@ -72,6 +83,10 @@ impl ResourceData { std::thread::current().id() ); } + + // TODO: Handle no_std non-send. + // Currently, no_std is single-threaded only, so this is safe to ignore. + // To support no_std multithreading, an alternative will be required. } /// Returns true if the resource is populated. @@ -182,6 +197,7 @@ impl ResourceData { self.data.replace_unchecked(Self::ROW, value); } } else { + #[cfg(feature = "std")] if !SEND { self.origin_thread_id = Some(std::thread::current().id()); } @@ -220,6 +236,7 @@ impl ResourceData { self.data.replace_unchecked(Self::ROW, value); } } else { + #[cfg(feature = "std")] if !SEND { self.origin_thread_id = Some(std::thread::current().id()); } @@ -373,6 +390,7 @@ impl Resources { changed_ticks: UnsafeCell::new(Tick::new(0)), type_name: String::from(component_info.name()), id: f(), + #[cfg(feature = "std")] origin_thread_id: None, #[cfg(feature = "track_change_detection")] changed_by: UnsafeCell::new(Location::caller()) diff --git a/crates/bevy_ecs/src/storage/sparse_set.rs b/crates/bevy_ecs/src/storage/sparse_set.rs index e3d76547a9118..14b135fd04241 100644 --- a/crates/bevy_ecs/src/storage/sparse_set.rs +++ b/crates/bevy_ecs/src/storage/sparse_set.rs @@ -4,6 +4,7 @@ use crate::{ entity::Entity, storage::{Column, TableRow}, }; +use alloc::{boxed::Box, vec::Vec}; use bevy_ptr::{OwningPtr, Ptr}; #[cfg(feature = "track_change_detection")] use core::panic::Location; diff --git a/crates/bevy_ecs/src/storage/table/column.rs b/crates/bevy_ecs/src/storage/table/column.rs index e2c16613b476f..f7ea1683e458f 100644 --- a/crates/bevy_ecs/src/storage/table/column.rs +++ b/crates/bevy_ecs/src/storage/table/column.rs @@ -3,6 +3,7 @@ use crate::{ component::TickCells, storage::{blob_array::BlobArray, thin_array_ptr::ThinArrayPtr}, }; +use alloc::vec::Vec; use bevy_ptr::PtrMut; /// Very similar to a normal [`Column`], but with the capacities and lengths cut out for performance reasons. diff --git a/crates/bevy_ecs/src/storage/table/mod.rs b/crates/bevy_ecs/src/storage/table/mod.rs index 5e7ed68f27780..1f82642c07d6b 100644 --- a/crates/bevy_ecs/src/storage/table/mod.rs +++ b/crates/bevy_ecs/src/storage/table/mod.rs @@ -5,6 +5,7 @@ use crate::{ query::DebugCheckedUnwrap, storage::{blob_vec::BlobVec, ImmutableSparseSet, SparseSet}, }; +use alloc::{boxed::Box, vec, vec::Vec}; use bevy_ptr::{OwningPtr, Ptr, UnsafeCellDeref}; use bevy_utils::HashMap; pub use column::*; diff --git a/crates/bevy_ecs/src/storage/thin_array_ptr.rs b/crates/bevy_ecs/src/storage/thin_array_ptr.rs index e6ed11774bd97..9c073324559d3 100644 --- a/crates/bevy_ecs/src/storage/thin_array_ptr.rs +++ b/crates/bevy_ecs/src/storage/thin_array_ptr.rs @@ -1,5 +1,8 @@ use crate::query::DebugCheckedUnwrap; -use alloc::alloc::{alloc, handle_alloc_error, realloc}; +use alloc::{ + alloc::{alloc, handle_alloc_error, realloc}, + boxed::Box, +}; use core::{ alloc::Layout, mem::{needs_drop, size_of}, diff --git a/crates/bevy_ecs/src/system/adapter_system.rs b/crates/bevy_ecs/src/system/adapter_system.rs index ef5e51c08f8e2..27e812928c8a1 100644 --- a/crates/bevy_ecs/src/system/adapter_system.rs +++ b/crates/bevy_ecs/src/system/adapter_system.rs @@ -1,4 +1,4 @@ -use alloc::borrow::Cow; +use alloc::{borrow::Cow, vec::Vec}; use super::{IntoSystem, ReadOnlySystem, System}; use crate::{ diff --git a/crates/bevy_ecs/src/system/builder.rs b/crates/bevy_ecs/src/system/builder.rs index d474a52de0987..fe68ea6bfa6a7 100644 --- a/crates/bevy_ecs/src/system/builder.rs +++ b/crates/bevy_ecs/src/system/builder.rs @@ -1,3 +1,4 @@ +use alloc::{boxed::Box, vec::Vec}; use bevy_utils::synccell::SyncCell; use variadics_please::all_tuples; diff --git a/crates/bevy_ecs/src/system/combinator.rs b/crates/bevy_ecs/src/system/combinator.rs index e21f35eee4e82..9d8652e9dbc00 100644 --- a/crates/bevy_ecs/src/system/combinator.rs +++ b/crates/bevy_ecs/src/system/combinator.rs @@ -1,4 +1,4 @@ -use alloc::borrow::Cow; +use alloc::{borrow::Cow, format, vec::Vec}; use core::marker::PhantomData; use crate::{ diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs index a2cbbea764c37..7955a2d03f305 100644 --- a/crates/bevy_ecs/src/system/commands/mod.rs +++ b/crates/bevy_ecs/src/system/commands/mod.rs @@ -1,5 +1,7 @@ +#[cfg(feature = "std")] mod parallel_scope; +use alloc::vec::Vec; use core::{marker::PhantomData, panic::Location}; use super::{ @@ -22,7 +24,9 @@ use crate::{ }, }; use bevy_ptr::OwningPtr; -use bevy_utils::tracing::{error, info}; +use log::{error, info}; + +#[cfg(feature = "std")] pub use parallel_scope::*; /// A [`Command`] queue to perform structural changes to the [`World`]. diff --git a/crates/bevy_ecs/src/system/exclusive_function_system.rs b/crates/bevy_ecs/src/system/exclusive_function_system.rs index 2face3a9f0cb3..99f3d1d0299af 100644 --- a/crates/bevy_ecs/src/system/exclusive_function_system.rs +++ b/crates/bevy_ecs/src/system/exclusive_function_system.rs @@ -10,7 +10,7 @@ use crate::{ world::{unsafe_world_cell::UnsafeWorldCell, World}, }; -use alloc::borrow::Cow; +use alloc::{borrow::Cow, vec, vec::Vec}; use core::marker::PhantomData; use variadics_please::all_tuples; diff --git a/crates/bevy_ecs/src/system/function_system.rs b/crates/bevy_ecs/src/system/function_system.rs index 87950de4e4fb8..3d029d74a9577 100644 --- a/crates/bevy_ecs/src/system/function_system.rs +++ b/crates/bevy_ecs/src/system/function_system.rs @@ -11,12 +11,12 @@ use crate::{ world::{unsafe_world_cell::UnsafeWorldCell, DeferredWorld, World, WorldId}, }; -use alloc::borrow::Cow; +use alloc::{borrow::Cow, vec, vec::Vec}; use core::marker::PhantomData; use variadics_please::all_tuples; #[cfg(feature = "trace")] -use bevy_utils::tracing::{info_span, Span}; +use tracing::{info_span, Span}; use super::{In, IntoSystem, ReadOnlySystem, SystemParamBuilder}; @@ -213,7 +213,7 @@ impl ParamWarnPolicy { return; } - bevy_utils::tracing::warn!( + log::warn!( "{0} did not run because it requested inaccessible system parameter {1}", name, disqualified::ShortName::of::

() diff --git a/crates/bevy_ecs/src/system/mod.rs b/crates/bevy_ecs/src/system/mod.rs index 58f5800ede3ed..4a4c9e48af230 100644 --- a/crates/bevy_ecs/src/system/mod.rs +++ b/crates/bevy_ecs/src/system/mod.rs @@ -1651,7 +1651,13 @@ mod tests { assert_is_system(returning::>.map(drop)); assert_is_system(returning::<&str>.map(u64::from_str).map(Result::unwrap)); assert_is_system(static_system_param); - assert_is_system(exclusive_in_out::<(), Result<(), std::io::Error>>.map(bevy_utils::error)); + assert_is_system( + exclusive_in_out::<(), Result<(), std::io::Error>>.map(|result| { + if let Err(error) = result { + log::error!("{:?}", error); + } + }), + ); assert_is_system(exclusive_with_state); assert_is_system(returning::.pipe(exclusive_in_out::)); diff --git a/crates/bevy_ecs/src/system/schedule_system.rs b/crates/bevy_ecs/src/system/schedule_system.rs index c88db47f04936..042e69b675955 100644 --- a/crates/bevy_ecs/src/system/schedule_system.rs +++ b/crates/bevy_ecs/src/system/schedule_system.rs @@ -1,4 +1,4 @@ -use alloc::borrow::Cow; +use alloc::{borrow::Cow, vec::Vec}; use core::any::TypeId; use crate::{ diff --git a/crates/bevy_ecs/src/system/system.rs b/crates/bevy_ecs/src/system/system.rs index c1c628cb2e1aa..d4d8ddb8a7e45 100644 --- a/crates/bevy_ecs/src/system/system.rs +++ b/crates/bevy_ecs/src/system/system.rs @@ -1,5 +1,5 @@ -use bevy_utils::tracing::warn; use core::fmt::Debug; +use log::warn; use thiserror::Error; use crate::{ @@ -11,7 +11,7 @@ use crate::{ world::{unsafe_world_cell::UnsafeWorldCell, DeferredWorld, World}, }; -use alloc::borrow::Cow; +use alloc::{borrow::Cow, boxed::Box, vec::Vec}; use core::any::TypeId; use super::IntoSystem; diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 2186e2b8a3d10..2af839da2ca4e 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -16,6 +16,7 @@ use crate::{ FromWorld, World, }, }; +use alloc::{borrow::ToOwned, boxed::Box, vec::Vec}; use bevy_ecs_macros::impl_param_set; pub use bevy_ecs_macros::{Resource, SystemParam}; use bevy_ptr::UnsafeCellDeref; diff --git a/crates/bevy_ecs/src/system/system_registry.rs b/crates/bevy_ecs/src/system/system_registry.rs index f00740a1f7942..ffcf77f677917 100644 --- a/crates/bevy_ecs/src/system/system_registry.rs +++ b/crates/bevy_ecs/src/system/system_registry.rs @@ -8,6 +8,7 @@ use crate::{ system::{input::SystemInput, BoxedSystem, IntoSystem, System}, world::{Command, World}, }; +use alloc::boxed::Box; use bevy_ecs_macros::{Component, Resource}; #[cfg(feature = "bevy_reflect")] use bevy_reflect::Reflect; diff --git a/crates/bevy_ecs/src/world/command_queue.rs b/crates/bevy_ecs/src/world/command_queue.rs index 9fd3a06b9d8ef..014c5b21c5895 100644 --- a/crates/bevy_ecs/src/world/command_queue.rs +++ b/crates/bevy_ecs/src/world/command_queue.rs @@ -7,8 +7,9 @@ use core::{ ptr::{addr_of_mut, NonNull}, }; +use alloc::{boxed::Box, vec::Vec}; use bevy_ptr::{OwningPtr, Unaligned}; -use bevy_utils::tracing::warn; +use log::warn; use crate::world::{Command, World}; @@ -261,7 +262,7 @@ impl RawCommandQueue { self.bytes.as_mut().as_mut_ptr().add(local_cursor).cast(), )) }; - let result = std::panic::catch_unwind(AssertUnwindSafe(|| { + let f = AssertUnwindSafe(|| { // SAFETY: The data underneath the cursor must correspond to the type erased in metadata, // since they were stored next to each other by `.push()`. // For ZSTs, the type doesn't matter as long as the pointer is non-null. @@ -269,33 +270,41 @@ impl RawCommandQueue { // At this point, it will either point to the next `CommandMeta`, // or the cursor will be out of bounds and the loop will end. unsafe { (meta.consume_command_and_get_size)(cmd, world, &mut local_cursor) }; - })); - - if let Err(payload) = result { - // local_cursor now points to the location _after_ the panicked command. - // Add the remaining commands that _would have_ been applied to the - // panic_recovery queue. - // - // This uses `current_stop` instead of `stop` to account for any commands - // that were queued _during_ this panic. - // - // This is implemented in such a way that if apply_or_drop_queued() are nested recursively in, - // an applied Command, the correct command order will be retained. - let panic_recovery = self.panic_recovery.as_mut(); - let bytes = self.bytes.as_mut(); - let current_stop = bytes.len(); - panic_recovery.extend_from_slice(&bytes[local_cursor..current_stop]); - bytes.set_len(start); - *self.cursor.as_mut() = start; - - // This was the "top of the apply stack". If we are _not_ at the top of the apply stack, - // when we call`resume_unwind" the caller "closer to the top" will catch the unwind and do this check, - // until we reach the top. - if start == 0 { - bytes.append(panic_recovery); + }); + + #[cfg(feature = "std")] + { + let result = std::panic::catch_unwind(f); + + if let Err(payload) = result { + // local_cursor now points to the location _after_ the panicked command. + // Add the remaining commands that _would have_ been applied to the + // panic_recovery queue. + // + // This uses `current_stop` instead of `stop` to account for any commands + // that were queued _during_ this panic. + // + // This is implemented in such a way that if apply_or_drop_queued() are nested recursively in, + // an applied Command, the correct command order will be retained. + let panic_recovery = self.panic_recovery.as_mut(); + let bytes = self.bytes.as_mut(); + let current_stop = bytes.len(); + panic_recovery.extend_from_slice(&bytes[local_cursor..current_stop]); + bytes.set_len(start); + *self.cursor.as_mut() = start; + + // This was the "top of the apply stack". If we are _not_ at the top of the apply stack, + // when we call`resume_unwind" the caller "closer to the top" will catch the unwind and do this check, + // until we reach the top. + if start == 0 { + bytes.append(panic_recovery); + } + std::panic::resume_unwind(payload); } - std::panic::resume_unwind(payload); } + + #[cfg(not(feature = "std"))] + (f)(); } // Reset the buffer: all commands past the original `start` cursor have been applied. diff --git a/crates/bevy_ecs/src/world/deferred_world.rs b/crates/bevy_ecs/src/world/deferred_world.rs index 3002a11f58667..c66bcc53c869a 100644 --- a/crates/bevy_ecs/src/world/deferred_world.rs +++ b/crates/bevy_ecs/src/world/deferred_world.rs @@ -356,7 +356,7 @@ impl<'w> DeferredWorld<'w> { events: impl IntoIterator, ) -> Option> { let Some(mut events_resource) = self.get_resource_mut::>() else { - bevy_utils::tracing::error!( + log::error!( "Unable to send event `{}`\n\tEvent must be added to the app with `add_event()`\n\thttps://docs.rs/bevy/*/bevy/app/struct.App.html#method.add_event ", core::any::type_name::() ); diff --git a/crates/bevy_ecs/src/world/entity_fetch.rs b/crates/bevy_ecs/src/world/entity_fetch.rs index 62d63ced54fb7..2f8b0365ebf0d 100644 --- a/crates/bevy_ecs/src/world/entity_fetch.rs +++ b/crates/bevy_ecs/src/world/entity_fetch.rs @@ -1,3 +1,4 @@ +use alloc::vec::Vec; use core::mem::MaybeUninit; use crate::{ diff --git a/crates/bevy_ecs/src/world/entity_ref.rs b/crates/bevy_ecs/src/world/entity_ref.rs index 0ac19e312b878..47873635c5902 100644 --- a/crates/bevy_ecs/src/world/entity_ref.rs +++ b/crates/bevy_ecs/src/world/entity_ref.rs @@ -12,6 +12,7 @@ use crate::{ system::IntoObserverSystem, world::{error::EntityComponentError, DeferredWorld, Mut, World}, }; +use alloc::vec::Vec; use bevy_ptr::{OwningPtr, Ptr}; use bevy_utils::{HashMap, HashSet}; use core::{any::TypeId, marker::PhantomData, mem::MaybeUninit}; diff --git a/crates/bevy_ecs/src/world/filtered_resource.rs b/crates/bevy_ecs/src/world/filtered_resource.rs index 527957d87c89d..659d9d9ab7206 100644 --- a/crates/bevy_ecs/src/world/filtered_resource.rs +++ b/crates/bevy_ecs/src/world/filtered_resource.rs @@ -1,5 +1,9 @@ +#[cfg(feature = "std")] use std::sync::OnceLock; +#[cfg(not(feature = "std"))] +use spin::once::Once as OnceLock; + use crate::{ change_detection::{Mut, MutUntyped, Ref, Ticks, TicksMut}, component::{ComponentId, Tick}, @@ -217,11 +221,21 @@ impl<'w, 's> From<&'w FilteredResourcesMut<'_, 's>> for FilteredResources<'w, 's impl<'w> From<&'w World> for FilteredResources<'w, 'static> { fn from(value: &'w World) -> Self { static READ_ALL_RESOURCES: OnceLock> = OnceLock::new(); - let access = READ_ALL_RESOURCES.get_or_init(|| { - let mut access = Access::new(); - access.read_all_resources(); + let access = { + let init = || { + let mut access = Access::new(); + access.read_all_resources(); + access + }; + + #[cfg(feature = "std")] + let access = READ_ALL_RESOURCES.get_or_init(init); + + #[cfg(not(feature = "std"))] + let access = READ_ALL_RESOURCES.call_once(init); + access - }); + }; let last_run = value.last_change_tick(); let this_run = value.read_change_tick(); @@ -494,11 +508,22 @@ impl<'w, 's> FilteredResourcesMut<'w, 's> { impl<'w> From<&'w mut World> for FilteredResourcesMut<'w, 'static> { fn from(value: &'w mut World) -> Self { static WRITE_ALL_RESOURCES: OnceLock> = OnceLock::new(); - let access = WRITE_ALL_RESOURCES.get_or_init(|| { - let mut access = Access::new(); - access.write_all_resources(); + + let access = { + let init = || { + let mut access = Access::new(); + access.write_all_resources(); + access + }; + + #[cfg(feature = "std")] + let access = WRITE_ALL_RESOURCES.get_or_init(init); + + #[cfg(not(feature = "std"))] + let access = WRITE_ALL_RESOURCES.call_once(init); + access - }); + }; let last_run = value.last_change_tick(); let this_run = value.change_tick(); diff --git a/crates/bevy_ecs/src/world/identifier.rs b/crates/bevy_ecs/src/world/identifier.rs index 9187b818504b5..b1342e04dcc35 100644 --- a/crates/bevy_ecs/src/world/identifier.rs +++ b/crates/bevy_ecs/src/world/identifier.rs @@ -4,8 +4,13 @@ use crate::{ system::{ExclusiveSystemParam, ReadOnlySystemParam, SystemMeta, SystemParam}, world::{FromWorld, World}, }; + +#[cfg(not(feature = "portable-atomic"))] use core::sync::atomic::{AtomicUsize, Ordering}; +#[cfg(feature = "portable-atomic")] +use portable_atomic::{AtomicUsize, Ordering}; + use super::unsafe_world_cell::UnsafeWorldCell; #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 5152e549a8ee4..9e1a4099abc70 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -51,13 +51,16 @@ use crate::{ error::{EntityFetchError, TryRunScheduleError}, }, }; +use alloc::{boxed::Box, vec::Vec}; use bevy_ptr::{OwningPtr, Ptr}; -use bevy_utils::tracing::warn; -use core::{ - any::TypeId, - fmt, - sync::atomic::{AtomicU32, Ordering}, -}; +use core::{any::TypeId, fmt}; +use log::warn; + +#[cfg(not(feature = "portable-atomic"))] +use core::sync::atomic::{AtomicU32, Ordering}; + +#[cfg(feature = "portable-atomic")] +use portable_atomic::{AtomicU32, Ordering}; #[cfg(feature = "track_change_detection")] use bevy_ptr::UnsafeCellDeref; @@ -2964,7 +2967,7 @@ impl World { events: impl IntoIterator, ) -> Option> { let Some(mut events_resource) = self.get_resource_mut::>() else { - bevy_utils::tracing::error!( + log::error!( "Unable to send event `{}`\n\tEvent must be added to the app with `add_event()`\n\thttps://docs.rs/bevy/*/bevy/app/struct.App.html#method.add_event ", core::any::type_name::() ); @@ -3293,7 +3296,7 @@ impl World { } = self.storages; #[cfg(feature = "trace")] - let _span = bevy_utils::tracing::info_span!("check component ticks").entered(); + let _span = tracing::info_span!("check component ticks").entered(); tables.check_change_ticks(change_tick); sparse_sets.check_change_ticks(change_tick); resources.check_change_ticks(change_tick); diff --git a/crates/bevy_ecs/src/world/reflect.rs b/crates/bevy_ecs/src/world/reflect.rs index 71dc7a5222189..2763d55278e66 100644 --- a/crates/bevy_ecs/src/world/reflect.rs +++ b/crates/bevy_ecs/src/world/reflect.rs @@ -4,6 +4,7 @@ use core::any::TypeId; use thiserror::Error; +use alloc::string::String; use bevy_reflect::{Reflect, ReflectFromPtr}; use crate::{prelude::*, world::ComponentId}; diff --git a/crates/bevy_ecs/src/world/unsafe_world_cell.rs b/crates/bevy_ecs/src/world/unsafe_world_cell.rs index aed797c5551e5..e14fd3893a06a 100644 --- a/crates/bevy_ecs/src/world/unsafe_world_cell.rs +++ b/crates/bevy_ecs/src/world/unsafe_world_cell.rs @@ -23,6 +23,12 @@ use bevy_ptr::UnsafeCellDeref; use core::{any::TypeId, cell::UnsafeCell, fmt::Debug, marker::PhantomData, ptr}; use thiserror::Error; +#[cfg(not(feature = "portable-atomic"))] +use core::sync::atomic::Ordering; + +#[cfg(feature = "portable-atomic")] +use portable_atomic::Ordering; + /// Variant of the [`World`] where resource and component accesses take `&self`, and the responsibility to avoid /// aliasing violations are given to the caller instead of being checked at compile-time by rust's unique XOR shared rule. /// @@ -304,7 +310,7 @@ impl<'w> UnsafeWorldCell<'w> { let change_tick = unsafe { &self.world_metadata().change_tick }; // NOTE: We can used a relaxed memory ordering here, since nothing // other than the atomic value itself is relying on atomic synchronization - Tick::new(change_tick.fetch_add(1, core::sync::atomic::Ordering::Relaxed)) + Tick::new(change_tick.fetch_add(1, Ordering::Relaxed)) } /// Provides unchecked access to the internal data stores of the [`World`]. diff --git a/crates/bevy_utils/Cargo.toml b/crates/bevy_utils/Cargo.toml index 91bf2710e0aee..80c84a5dfc384 100644 --- a/crates/bevy_utils/Cargo.toml +++ b/crates/bevy_utils/Cargo.toml @@ -9,22 +9,23 @@ license = "MIT OR Apache-2.0" keywords = ["bevy"] [features] -default = ["std", "serde"] +default = ["std", "serde", "tracing"] std = [ "alloc", - "tracing/std", + "tracing?/std", "ahash/std", "dep:thread_local", "ahash/runtime-rng", ] alloc = ["hashbrown/default"] serde = ["hashbrown/serde"] +tracing = ["dep:tracing"] [dependencies] ahash = { version = "0.8.7", default-features = false, features = [ "compile-time-rng", ] } -tracing = { version = "0.1", default-features = false } +tracing = { version = "0.1", default-features = false, optional = true } hashbrown = { version = "0.14.2", default-features = false } thread_local = { version = "1.0", optional = true } diff --git a/crates/bevy_utils/src/lib.rs b/crates/bevy_utils/src/lib.rs index 00329f652b02f..bd04bea210e67 100644 --- a/crates/bevy_utils/src/lib.rs +++ b/crates/bevy_utils/src/lib.rs @@ -41,6 +41,7 @@ pub use hashbrown; #[cfg(feature = "std")] pub use parallel_queue::*; pub use time::*; +#[cfg(feature = "tracing")] pub use tracing; #[cfg(feature = "alloc")] @@ -385,16 +386,19 @@ impl Drop for OnDrop { } /// Calls the [`tracing::info!`] macro on a value. +#[cfg(feature = "tracing")] pub fn info(data: T) { tracing::info!("{:?}", data); } /// Calls the [`tracing::debug!`] macro on a value. +#[cfg(feature = "tracing")] pub fn dbg(data: T) { tracing::debug!("{:?}", data); } /// Processes a [`Result`] by calling the [`tracing::warn!`] macro in case of an [`Err`] value. +#[cfg(feature = "tracing")] pub fn warn(result: Result<(), E>) { if let Err(warn) = result { tracing::warn!("{:?}", warn); @@ -402,6 +406,7 @@ pub fn warn(result: Result<(), E>) { } /// Processes a [`Result`] by calling the [`tracing::error!`] macro in case of an [`Err`] value. +#[cfg(feature = "tracing")] pub fn error(result: Result<(), E>) { if let Err(error) = result { tracing::error!("{:?}", error); @@ -409,6 +414,7 @@ pub fn error(result: Result<(), E>) { } /// Like [`tracing::trace`], but conditional on cargo feature `detailed_trace`. +#[cfg(feature = "tracing")] #[macro_export] macro_rules! detailed_trace { ($($tts:tt)*) => { diff --git a/tools/ci/src/commands/compile_check_no_std.rs b/tools/ci/src/commands/compile_check_no_std.rs index 6e057ba4d2050..9ce1134855cc0 100644 --- a/tools/ci/src/commands/compile_check_no_std.rs +++ b/tools/ci/src/commands/compile_check_no_std.rs @@ -94,6 +94,14 @@ impl Prepare for CompileCheckNoStdCommand { "Please fix compiler errors in output above for bevy_tasks no_std compatibility.", )); + commands.push(PreparedCommand::new::( + cmd!( + sh, + "cargo check -p bevy_ecs --no-default-features --features edge_executor,critical-section --target {target}" + ), + "Please fix compiler errors in output above for bevy_ecs no_std compatibility.", + )); + commands } } From c21878b238aa5d32feb53c55884030d83707e0a5 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Wed, 11 Dec 2024 10:13:28 +1100 Subject: [PATCH 2/4] Fix for coercion --- crates/bevy_ecs/src/component.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_ecs/src/component.rs b/crates/bevy_ecs/src/component.rs index b1e6c25cbd46d..9cfe1351c2ee9 100644 --- a/crates/bevy_ecs/src/component.rs +++ b/crates/bevy_ecs/src/component.rs @@ -2014,12 +2014,12 @@ impl RequiredComponents { dyn for<'a, 'b> Fn(&'a mut Table, &'b mut SparseSets, Tick, TableRow, Entity); #[cfg(feature = "portable-atomic")] - type BoxedRequiredComponentConstructor = Box; + type Intermediate = Box; #[cfg(not(feature = "portable-atomic"))] - type BoxedRequiredComponentConstructor = Arc; + type Intermediate = Arc; - let boxed: BoxedRequiredComponentConstructor = Box::new( + let boxed: Intermediate = Intermediate::new( move |table, sparse_sets, change_tick, From 98837bf569b22d48cbfe778a05a28e7f6e21527c Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Wed, 11 Dec 2024 15:39:34 +1100 Subject: [PATCH 3/4] Ensure `bevy_reflect` works with `no_std` `bevy_ecs` --- crates/bevy_ecs/Cargo.toml | 6 +----- crates/bevy_ecs/src/world/reflect.rs | 2 +- tools/ci/src/commands/compile_check_no_std.rs | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/crates/bevy_ecs/Cargo.toml b/crates/bevy_ecs/Cargo.toml index f7ac0e430e91b..dabd9e9f70dae 100644 --- a/crates/bevy_ecs/Cargo.toml +++ b/crates/bevy_ecs/Cargo.toml @@ -48,13 +48,9 @@ portable-atomic = [ "concurrent-queue/portable-atomic", ] - [dependencies] bevy_ptr = { path = "../bevy_ptr", version = "0.15.0-dev" } -bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", default-features = false, features = [ - "smallvec", - "debug", -], optional = true } +bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", default-features = false, optional = true } bevy_tasks = { path = "../bevy_tasks", version = "0.15.0-dev", default-features = false } bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev", default-features = false, features = [ "alloc", diff --git a/crates/bevy_ecs/src/world/reflect.rs b/crates/bevy_ecs/src/world/reflect.rs index 2763d55278e66..afa2015f4ef38 100644 --- a/crates/bevy_ecs/src/world/reflect.rs +++ b/crates/bevy_ecs/src/world/reflect.rs @@ -4,7 +4,7 @@ use core::any::TypeId; use thiserror::Error; -use alloc::string::String; +use alloc::string::{String, ToString}; use bevy_reflect::{Reflect, ReflectFromPtr}; use crate::{prelude::*, world::ComponentId}; diff --git a/tools/ci/src/commands/compile_check_no_std.rs b/tools/ci/src/commands/compile_check_no_std.rs index 9ce1134855cc0..02bfd7c58790f 100644 --- a/tools/ci/src/commands/compile_check_no_std.rs +++ b/tools/ci/src/commands/compile_check_no_std.rs @@ -97,7 +97,7 @@ impl Prepare for CompileCheckNoStdCommand { commands.push(PreparedCommand::new::( cmd!( sh, - "cargo check -p bevy_ecs --no-default-features --features edge_executor,critical-section --target {target}" + "cargo check -p bevy_ecs --no-default-features --features edge_executor,critical-section,bevy_debug_stepping,bevy_reflect --target {target}" ), "Please fix compiler errors in output above for bevy_ecs no_std compatibility.", )); From cac396bd514cd88da437eb6020cdbd3e43310925 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Wed, 11 Dec 2024 16:02:13 +1100 Subject: [PATCH 4/4] Fix issue where `Component` macro was not accessing `Vec` in a `no_std` compatible way --- crates/bevy_ecs/macros/src/component.rs | 2 +- crates/bevy_ecs/src/component.rs | 2 +- crates/bevy_ecs/src/lib.rs | 11 +++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/macros/src/component.rs b/crates/bevy_ecs/macros/src/component.rs index 84c69467a797f..cd7cd52bf6570 100644 --- a/crates/bevy_ecs/macros/src/component.rs +++ b/crates/bevy_ecs/macros/src/component.rs @@ -149,7 +149,7 @@ pub fn derive_component(input: TokenStream) -> TokenStream { storages: &mut #bevy_ecs_path::storage::Storages, required_components: &mut #bevy_ecs_path::component::RequiredComponents, inheritance_depth: u16, - recursion_check_stack: &mut Vec<#bevy_ecs_path::component::ComponentId> + recursion_check_stack: &mut #bevy_ecs_path::__macro_exports::Vec<#bevy_ecs_path::component::ComponentId> ) { #bevy_ecs_path::component::enforce_no_required_components_recursion(components, recursion_check_stack); let self_id = components.register_component::(storages); diff --git a/crates/bevy_ecs/src/component.rs b/crates/bevy_ecs/src/component.rs index b66de1239aaa1..29b375896a197 100644 --- a/crates/bevy_ecs/src/component.rs +++ b/crates/bevy_ecs/src/component.rs @@ -11,7 +11,7 @@ use crate::{ system::{Local, Resource, SystemParam}, world::{DeferredWorld, FromWorld, World}, }; -use alloc::{borrow::Cow, vec::Vec}; +use alloc::{borrow::Cow, format, vec::Vec}; pub use bevy_ecs_macros::Component; use bevy_ptr::{OwningPtr, UnsafeCellDeref}; #[cfg(feature = "bevy_reflect")] diff --git a/crates/bevy_ecs/src/lib.rs b/crates/bevy_ecs/src/lib.rs index 22dd2e32ea941..ac7eeaec8cc04 100644 --- a/crates/bevy_ecs/src/lib.rs +++ b/crates/bevy_ecs/src/lib.rs @@ -89,6 +89,17 @@ pub mod prelude { pub use crate::reflect::AppFunctionRegistry; } +/// Exports used by macros. +/// +/// These are not meant to be used directly and are subject to breaking changes. +#[doc(hidden)] +pub mod __macro_exports { + // Cannot directly use `alloc::vec::Vec` in macros, as a crate may not have + // included `extern crate alloc;`. This re-export ensures we have access + // to `Vec` in `no_std` and `std` contexts. + pub use alloc::vec::Vec; +} + #[cfg(test)] mod tests { use crate as bevy_ecs;