From 31054b498a761809cfe523f518e56db73a4fc8b4 Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Sat, 6 Nov 2021 01:24:55 -0400 Subject: [PATCH 01/13] Add Commands::init_resource --- crates/bevy_ecs/src/system/commands/mod.rs | 41 +++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs index 608f8eeb551d3..c8fc6c637d9a2 100644 --- a/crates/bevy_ecs/src/system/commands/mod.rs +++ b/crates/bevy_ecs/src/system/commands/mod.rs @@ -4,7 +4,7 @@ use crate::{ bundle::Bundle, component::Component, entity::{Entities, Entity}, - world::World, + world::{FromWorld, World}, }; use bevy_utils::tracing::{error, warn}; pub use command_queue::CommandQueue; @@ -261,6 +261,34 @@ impl<'w, 's> Commands<'w, 's> { self.queue.push(InsertOrSpawnBatch { bundles_iter }); } + /// Inserts a resource with default values to the [`World`], overwriting any previous value of the same type. + /// + /// The value given by the [`FromWorld::from_world`] method will be used. + /// Note that any resource with the `Default` trait automatically implements `FromWorld`, + /// and those default values will be here instead. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # #[derive(Default)] + /// # struct Scoreboard { + /// # current_score: u32, + /// # high_score: u32, + /// # } + /// # + /// # fn system(mut commands: Commands) { + /// commands.init_resource::(); + /// # } + /// # system.system(); + /// ``` + pub fn init_resource(&mut self) { + self.queue.push(InitResource:: { + _phantom: PhantomData::::default(), + }) + } + /// Inserts a resource to the [`World`], overwriting any previous value of the same type. /// /// See [`World::insert_resource`] for more details. @@ -713,6 +741,17 @@ where } } +pub struct InitResource { + _phantom: PhantomData, +} + +impl Command for InitResource { + fn write(self, world: &mut World) { + let resource: T = FromWorld::from_world(world); + world.insert_resource(resource); + } +} + pub struct InsertResource { pub resource: T, } From 7a5aa5dfb8e30b835a265b7568bde6d92f0b1789 Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Sat, 6 Nov 2021 01:30:50 -0400 Subject: [PATCH 02/13] Implement `World.init_resource` --- crates/bevy_ecs/src/system/commands/mod.rs | 5 +++-- crates/bevy_ecs/src/world/mod.rs | 10 ++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs index c8fc6c637d9a2..63fd0804d9ee5 100644 --- a/crates/bevy_ecs/src/system/commands/mod.rs +++ b/crates/bevy_ecs/src/system/commands/mod.rs @@ -267,6 +267,8 @@ impl<'w, 's> Commands<'w, 's> { /// Note that any resource with the `Default` trait automatically implements `FromWorld`, /// and those default values will be here instead. /// + /// See [`World::init_resource`] for more details. + /// /// # Example /// /// ``` @@ -747,8 +749,7 @@ pub struct InitResource { impl Command for InitResource { fn write(self, world: &mut World) { - let resource: T = FromWorld::from_world(world); - world.insert_resource(resource); + world.init_resource::(); } } diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index c39528285ebd5..d9246d98bb0e4 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -592,6 +592,16 @@ impl World { } } + /// Inserts a new resource with default values. + /// + /// Uses the [`FromWorld`] trait to determine values, + /// which has a blanket impl for all `T: Default`. + #[inline] + pub fn init_resource(&mut self) { + let resource: T = FromWorld::from_world(self); + self.insert_resource(resource); + } + /// Inserts a new resource with the given `value`. /// Resources are "unique" data of a given type. #[inline] From 734d54b3583fc177de08a4a22fd2f16a66a54536 Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Sat, 6 Nov 2021 01:38:46 -0400 Subject: [PATCH 03/13] Docs improvements --- crates/bevy_ecs/src/system/commands/mod.rs | 4 +++ crates/bevy_ecs/src/world/mod.rs | 39 +++++++++++++--------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs index 63fd0804d9ee5..0bb8d34c3686c 100644 --- a/crates/bevy_ecs/src/system/commands/mod.rs +++ b/crates/bevy_ecs/src/system/commands/mod.rs @@ -268,6 +268,8 @@ impl<'w, 's> Commands<'w, 's> { /// and those default values will be here instead. /// /// See [`World::init_resource`] for more details. + /// Note that commands do not take effect immediately. + /// When possible, prefer the equivalent methods on `App` or `World`. /// /// # Example /// @@ -294,6 +296,8 @@ impl<'w, 's> Commands<'w, 's> { /// Inserts a resource to the [`World`], overwriting any previous value of the same type. /// /// See [`World::insert_resource`] for more details. + /// Note that commands do not take effect immediately. + /// When possible, prefer the equivalent methods on `App` or `World`. /// /// # Example /// diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index d9246d98bb0e4..20aaf49e1a7e8 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -603,7 +603,10 @@ impl World { } /// Inserts a new resource with the given `value`. + /// /// Resources are "unique" data of a given type. + /// Insert a resource of a type that already exists + /// will overwrite any existing data. #[inline] pub fn insert_resource(&mut self, value: T) { let component_id = self.components.init_resource::(); @@ -612,7 +615,10 @@ impl World { } /// Inserts a new non-send resource with the given `value`. - /// Resources are "unique" data of a given type. + /// + /// NonSend resources cannot be sent across threads, + /// and do not need the `Send + Sync` bounds. + /// Systems with `NonSend` resources are always scheduled on the main thread. #[inline] pub fn insert_non_send(&mut self, value: T) { self.validate_non_send_access::(); @@ -622,7 +628,6 @@ impl World { } /// Removes the resource of a given type and returns it, if it exists. Otherwise returns [None]. - /// Resources are "unique" data of a given type. #[inline] pub fn remove_resource(&mut self) -> Option { // SAFE: T is Send + Sync @@ -638,7 +643,8 @@ impl World { #[inline] /// # Safety - /// make sure you're on main thread if T isn't Send + Sync + /// Only remove NonSend resources from the main thread + /// as they cannot be sent across theads #[allow(unused_unsafe)] pub unsafe fn remove_resource_unchecked(&mut self) -> Option { let component_id = self.components.get_resource_id(TypeId::of::())?; @@ -668,7 +674,6 @@ impl World { } /// Gets a reference to the resource of the given type, if it exists. Otherwise returns [None] - /// Resources are "unique" data of a given type. #[inline] pub fn get_resource(&self) -> Option<&T> { let component_id = self.components.get_resource_id(TypeId::of::())?; @@ -710,7 +715,6 @@ impl World { } /// Gets a mutable reference to the resource of the given type, if it exists. Otherwise returns - /// [None] Resources are "unique" data of a given type. #[inline] pub fn get_resource_mut(&mut self) -> Option> { // SAFE: unique world access @@ -718,8 +722,8 @@ impl World { } // PERF: optimize this to avoid redundant lookups - /// Gets a resource of type `T` if it exists, otherwise inserts the resource using the result of - /// calling `func`. + /// Gets a resource of type `T` if it exists, + /// otherwise inserts the resource using the result of calling `func`. #[inline] pub fn get_resource_or_insert_with( &mut self, @@ -731,8 +735,8 @@ impl World { self.get_resource_mut().unwrap() } - /// Gets a mutable reference to the resource of the given type, if it exists. Otherwise returns - /// [None] Resources are "unique" data of a given type. + /// Gets a mutable reference to the resource of the given type, if it exists + /// Otherwise returns [None] /// /// # Safety /// This will allow aliased mutable access to the given resource type. The caller must ensure @@ -743,8 +747,8 @@ impl World { self.get_resource_unchecked_mut_with_id(component_id) } - /// Gets a reference to the non-send resource of the given type, if it exists. Otherwise returns - /// [None] Resources are "unique" data of a given type. + /// Gets a reference to the non-send resource of the given type, if it exists. + /// Otherwise returns [None] #[inline] pub fn get_non_send_resource(&self) -> Option<&T> { let component_id = self.components.get_resource_id(TypeId::of::())?; @@ -752,16 +756,16 @@ impl World { unsafe { self.get_non_send_with_id(component_id) } } - /// Gets a mutable reference to the non-send resource of the given type, if it exists. Otherwise - /// returns [None] Resources are "unique" data of a given type. + /// Gets a mutable reference to the non-send resource of the given type, if it exists. + /// Otherwise returns [None] #[inline] pub fn get_non_send_resource_mut(&mut self) -> Option> { // SAFE: unique world access unsafe { self.get_non_send_resource_unchecked_mut() } } - /// Gets a mutable reference to the non-send resource of the given type, if it exists. Otherwise - /// returns [None] Resources are "unique" data of a given type. + /// Gets a mutable reference to the non-send resource of the given type, if it exists. + /// Otherwise returns [None] /// /// # Safety /// This will allow aliased mutable access to the given non-send resource type. The caller must @@ -1181,7 +1185,10 @@ impl fmt::Debug for World { unsafe impl Send for World {} unsafe impl Sync for World {} -/// Creates `Self` using data from the given [World] +/// Creates an instance of the type this trait is implemented for +/// using data from the supplied [World]. +/// +/// This can be helpful for complex initialization or context-aware defaults. pub trait FromWorld { /// Creates `Self` using data from the given [World] fn from_world(world: &mut World) -> Self; From 62f51d10528c97f34848d071ccc280c55d90b397 Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Sat, 6 Nov 2021 14:58:42 -0400 Subject: [PATCH 04/13] Use non-overwriting logic from #1349 --- crates/bevy_ecs/src/world/mod.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 20aaf49e1a7e8..bfc528decd6fb 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -594,12 +594,19 @@ impl World { /// Inserts a new resource with default values. /// + /// If the resource already exists, nothing happens. + /// /// Uses the [`FromWorld`] trait to determine values, /// which has a blanket impl for all `T: Default`. #[inline] - pub fn init_resource(&mut self) { - let resource: T = FromWorld::from_world(self); - self.insert_resource(resource); + pub fn init_resource(&mut self) { + // PERF: We could avoid double hashing here, since the `from_resources` call is guaranteed + // not to modify the map. However, we would need to be borrowing resources both + // mutably and immutably, so we would need to be extremely certain this is correct + if !self.contains_resource::() { + let resource = R::from_world(self); + self.insert_resource(resource); + } } /// Inserts a new resource with the given `value`. From 0322a1b835411a1898fe31c6d27ace1152ed9652 Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Sat, 6 Nov 2021 15:00:02 -0400 Subject: [PATCH 05/13] Add init_nonsend_resource to World --- crates/bevy_ecs/src/world/mod.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index bfc528decd6fb..5f4c3ecfad814 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -621,6 +621,23 @@ impl World { unsafe { self.insert_resource_with_id(component_id, value) }; } + /// Inserts a new resource with default values. + /// + /// If the resource already exists, nothing happens. + /// + /// Uses the [`FromWorld`] trait to determine values, + /// which has a blanket impl for all `T: Default`. + #[inline] + pub fn init_non_send_resource(&mut self) { + // PERF: We could avoid double hashing here, since the `from_resources` call is guaranteed + // not to modify the map. However, we would need to be borrowing resources both + // mutably and immutably, so we would need to be extremely certain this is correct + if !self.contains_resource::() { + let resource = R::from_world(self); + self.insert_non_send_resource(resource); + } + } + /// Inserts a new non-send resource with the given `value`. /// /// NonSend resources cannot be sent across threads, From d34f13cff1c1601af8b4c97bd1919553fa8cd7f4 Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Sat, 6 Nov 2021 15:00:22 -0400 Subject: [PATCH 06/13] Naming consistency pass --- crates/bevy_app/src/app.rs | 50 ++++------- crates/bevy_ecs/src/lib.rs | 6 +- .../src/schedule/executor_parallel.rs | 2 +- crates/bevy_ecs/src/system/commands/mod.rs | 38 ++++---- crates/bevy_ecs/src/system/mod.rs | 6 +- crates/bevy_ecs/src/world/mod.rs | 86 +++++++++---------- crates/bevy_log/src/lib.rs | 2 +- crates/bevy_winit/src/lib.rs | 3 +- 8 files changed, 88 insertions(+), 105 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index e514e77bcba98..86f633df9bf7f 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -647,18 +647,15 @@ impl App { /// App::new() /// .insert_resource(MyCounter { counter: 0 }); /// ``` - pub fn insert_resource(&mut self, resource: T) -> &mut Self - where - T: Resource, - { + pub fn insert_resource(&mut self, resource: R) -> &mut Self { self.world.insert_resource(resource); self } /// Inserts a non-send resource to the app /// - /// You usually want to use `insert_resource`, but there are some special cases when a resource must - /// be non-send. + /// You usually want to use `insert_resource`, + /// but there are some special cases when a resource cannot be sent across threads. /// /// ## Example /// ``` @@ -671,19 +668,16 @@ impl App { /// App::new() /// .insert_non_send_resource(MyCounter { counter: 0 }); /// ``` - pub fn insert_non_send_resource(&mut self, resource: T) -> &mut Self - where - T: 'static, - { - self.world.insert_non_send(resource); + pub fn insert_non_send_resource(&mut self, resource: R) -> &mut Self { + self.world.insert_non_send_resource(resource); self } - /// Initialize a resource in the current [`App`], if it does not exist yet + /// Initialize a resource with default values by adding it to the [`World`] /// /// If the resource already exists, nothing happens. /// - /// Adds a resource that implements `Default` or [`FromWorld`] trait. + /// The resource must implement either the `Default` or [`FromWorld`] trait. /// /// ## Example /// ``` @@ -704,32 +698,18 @@ impl App { /// App::new() /// .init_resource::(); /// ``` - pub fn init_resource(&mut self) -> &mut Self - where - R: FromWorld + Send + Sync + 'static, - { - // PERF: We could avoid double hashing here, since the `from_resources` call is guaranteed - // not to modify the map. However, we would need to be borrowing resources both - // mutably and immutably, so we would need to be extremely certain this is correct - if !self.world.contains_resource::() { - let resource = R::from_world(&mut self.world); - self.insert_resource(resource); - } + pub fn init_resource(&mut self) -> &mut Self { + self.world.init_resource::(); self } - /// Initialize a non-send resource in the current [`App`], if it does not exist yet. + /// Initialize a non-send resource with default values by adding it to the [`World`] /// - /// Adds a resource that implements `Default` or [`FromWorld`] trait. - pub fn init_non_send_resource(&mut self) -> &mut Self - where - R: FromWorld + 'static, - { - // See perf comment in init_resource - if self.world.get_non_send_resource::().is_none() { - let resource = R::from_world(&mut self.world); - self.world.insert_non_send(resource); - } + /// If the resource already exists, nothing happens. + /// + /// The resource must implement either the `Default` or [`FromWorld`] trait. + pub fn init_non_send_resource(&mut self) -> &mut Self { + self.world.init_non_send_resource::(); self } diff --git a/crates/bevy_ecs/src/lib.rs b/crates/bevy_ecs/src/lib.rs index 813935de1cec9..d48ea55929773 100644 --- a/crates/bevy_ecs/src/lib.rs +++ b/crates/bevy_ecs/src/lib.rs @@ -1181,8 +1181,8 @@ mod tests { #[test] fn non_send_resource() { let mut world = World::default(); - world.insert_non_send(123i32); - world.insert_non_send(456i64); + world.insert_non_send_resource(123i32); + world.insert_non_send_resource(456i64); assert_eq!(*world.get_non_send_resource::().unwrap(), 123); assert_eq!(*world.get_non_send_resource_mut::().unwrap(), 456); } @@ -1191,7 +1191,7 @@ mod tests { #[should_panic] fn non_send_resource_panic() { let mut world = World::default(); - world.insert_non_send(0i32); + world.insert_non_send_resource(0i32); std::thread::spawn(move || { let _ = world.get_non_send_resource_mut::(); }) diff --git a/crates/bevy_ecs/src/schedule/executor_parallel.rs b/crates/bevy_ecs/src/schedule/executor_parallel.rs index 99515de252bb0..c0acb5cbcfc14 100644 --- a/crates/bevy_ecs/src/schedule/executor_parallel.rs +++ b/crates/bevy_ecs/src/schedule/executor_parallel.rs @@ -476,7 +476,7 @@ mod tests { fn non_send_resource() { use std::thread; let mut world = World::new(); - world.insert_non_send(thread::current().id()); + world.insert_non_send_resource(thread::current().id()); fn non_send(thread_id: NonSend) { assert_eq!(thread::current().id(), *thread_id); } diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs index 0bb8d34c3686c..78d5afad6b086 100644 --- a/crates/bevy_ecs/src/system/commands/mod.rs +++ b/crates/bevy_ecs/src/system/commands/mod.rs @@ -261,7 +261,9 @@ impl<'w, 's> Commands<'w, 's> { self.queue.push(InsertOrSpawnBatch { bundles_iter }); } - /// Inserts a resource with default values to the [`World`], overwriting any previous value of the same type. + /// Inserts a resource with default values to the [`World`]. + /// + /// If the resource already exists, nothing happens. /// /// The value given by the [`FromWorld::from_world`] method will be used. /// Note that any resource with the `Default` trait automatically implements `FromWorld`, @@ -287,9 +289,9 @@ impl<'w, 's> Commands<'w, 's> { /// # } /// # system.system(); /// ``` - pub fn init_resource(&mut self) { - self.queue.push(InitResource:: { - _phantom: PhantomData::::default(), + pub fn init_resource(&mut self) { + self.queue.push(InitResource:: { + _phantom: PhantomData::::default(), }) } @@ -317,7 +319,7 @@ impl<'w, 's> Commands<'w, 's> { /// # } /// # bevy_ecs::system::assert_is_system(system); /// ``` - pub fn insert_resource(&mut self, resource: T) { + pub fn insert_resource(&mut self, resource: R) { self.queue.push(InsertResource { resource }) } @@ -340,8 +342,8 @@ impl<'w, 's> Commands<'w, 's> { /// # } /// # bevy_ecs::system::assert_is_system(system); /// ``` - pub fn remove_resource(&mut self) { - self.queue.push(RemoveResource:: { + pub fn remove_resource(&mut self) { + self.queue.push(RemoveResource:: { phantom: PhantomData, }); } @@ -747,33 +749,33 @@ where } } -pub struct InitResource { - _phantom: PhantomData, +pub struct InitResource { + _phantom: PhantomData, } -impl Command for InitResource { +impl Command for InitResource { fn write(self, world: &mut World) { - world.init_resource::(); + world.init_resource::(); } } -pub struct InsertResource { - pub resource: T, +pub struct InsertResource { + pub resource: R, } -impl Command for InsertResource { +impl Command for InsertResource { fn write(self, world: &mut World) { world.insert_resource(self.resource); } } -pub struct RemoveResource { - pub phantom: PhantomData, +pub struct RemoveResource { + pub phantom: PhantomData, } -impl Command for RemoveResource { +impl Command for RemoveResource { fn write(self, world: &mut World) { - world.remove_resource::(); + world.remove_resource::(); } } diff --git a/crates/bevy_ecs/src/system/mod.rs b/crates/bevy_ecs/src/system/mod.rs index 27b585e70f8e9..738c312c40d88 100644 --- a/crates/bevy_ecs/src/system/mod.rs +++ b/crates/bevy_ecs/src/system/mod.rs @@ -422,7 +422,7 @@ mod tests { world.insert_resource(false); struct NotSend1(std::rc::Rc); struct NotSend2(std::rc::Rc); - world.insert_non_send(NotSend1(std::rc::Rc::new(0))); + world.insert_non_send_resource(NotSend1(std::rc::Rc::new(0))); fn sys( op: Option>, @@ -446,8 +446,8 @@ mod tests { struct NotSend1(std::rc::Rc); struct NotSend2(std::rc::Rc); - world.insert_non_send(NotSend1(std::rc::Rc::new(1))); - world.insert_non_send(NotSend2(std::rc::Rc::new(2))); + world.insert_non_send_resource(NotSend1(std::rc::Rc::new(1))); + world.insert_non_send_resource(NotSend2(std::rc::Rc::new(2))); fn sys(_op: NonSend, mut _op2: NonSendMut, mut run: ResMut) { *run = true; diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 5f4c3ecfad814..d8b50bf87505a 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -644,23 +644,23 @@ impl World { /// and do not need the `Send + Sync` bounds. /// Systems with `NonSend` resources are always scheduled on the main thread. #[inline] - pub fn insert_non_send(&mut self, value: T) { - self.validate_non_send_access::(); - let component_id = self.components.init_non_send::(); - // SAFE: component_id just initialized and corresponds to resource of type T + pub fn insert_non_send_resource(&mut self, value: R) { + self.validate_non_send_access::(); + let component_id = self.components.init_non_send::(); + // SAFE: component_id just initialized and corresponds to resource of type R unsafe { self.insert_resource_with_id(component_id, value) }; } /// Removes the resource of a given type and returns it, if it exists. Otherwise returns [None]. #[inline] - pub fn remove_resource(&mut self) -> Option { - // SAFE: T is Send + Sync + pub fn remove_resource(&mut self) -> Option { + // SAFE: R is Send + Sync unsafe { self.remove_resource_unchecked() } } #[inline] - pub fn remove_non_send(&mut self) -> Option { - self.validate_non_send_access::(); + pub fn remove_non_send_resource(&mut self) -> Option { + self.validate_non_send_access::(); // SAFE: we are on main thread unsafe { self.remove_resource_unchecked() } } @@ -670,8 +670,8 @@ impl World { /// Only remove NonSend resources from the main thread /// as they cannot be sent across theads #[allow(unused_unsafe)] - pub unsafe fn remove_resource_unchecked(&mut self) -> Option { - let component_id = self.components.get_resource_id(TypeId::of::())?; + pub unsafe fn remove_resource_unchecked(&mut self) -> Option { + let component_id = self.components.get_resource_id(TypeId::of::())?; let resource_archetype = self.archetypes.resource_mut(); let unique_components = resource_archetype.unique_components_mut(); let column = unique_components.get_mut(component_id)?; @@ -679,17 +679,17 @@ impl World { return None; } // SAFE: if a resource column exists, row 0 exists as well. caller takes ownership of the - // ptr value / drop is called when T is dropped + // ptr value / drop is called when R is dropped let (ptr, _) = unsafe { column.swap_remove_and_forget_unchecked(0) }; - // SAFE: column is of type T - Some(unsafe { ptr.cast::().read() }) + // SAFE: column is of type R + Some(unsafe { ptr.cast::().read() }) } - /// Returns `true` if a resource of type `T` exists. Otherwise returns `false`. + /// Returns `true` if a resource of type `R` exists. Otherwise returns `false`. #[inline] - pub fn contains_resource(&self) -> bool { + pub fn contains_resource(&self) -> bool { let component_id = - if let Some(component_id) = self.components.get_resource_id(TypeId::of::()) { + if let Some(component_id) = self.components.get_resource_id(TypeId::of::()) { component_id } else { return false; @@ -699,14 +699,14 @@ impl World { /// Gets a reference to the resource of the given type, if it exists. Otherwise returns [None] #[inline] - pub fn get_resource(&self) -> Option<&T> { - let component_id = self.components.get_resource_id(TypeId::of::())?; + pub fn get_resource(&self) -> Option<&R> { + let component_id = self.components.get_resource_id(TypeId::of::())?; unsafe { self.get_resource_with_id(component_id) } } - pub fn is_resource_added(&self) -> bool { + pub fn is_resource_added(&self) -> bool { let component_id = - if let Some(component_id) = self.components.get_resource_id(TypeId::of::()) { + if let Some(component_id) = self.components.get_resource_id(TypeId::of::()) { component_id } else { return false; @@ -721,9 +721,9 @@ impl World { ticks.is_added(self.last_change_tick(), self.read_change_tick()) } - pub fn is_resource_changed(&self) -> bool { + pub fn is_resource_changed(&self) -> bool { let component_id = - if let Some(component_id) = self.components.get_resource_id(TypeId::of::()) { + if let Some(component_id) = self.components.get_resource_id(TypeId::of::()) { component_id } else { return false; @@ -740,7 +740,7 @@ impl World { /// Gets a mutable reference to the resource of the given type, if it exists. Otherwise returns #[inline] - pub fn get_resource_mut(&mut self) -> Option> { + pub fn get_resource_mut(&mut self) -> Option> { // SAFE: unique world access unsafe { self.get_resource_unchecked_mut() } } @@ -749,11 +749,11 @@ impl World { /// Gets a resource of type `T` if it exists, /// otherwise inserts the resource using the result of calling `func`. #[inline] - pub fn get_resource_or_insert_with( + pub fn get_resource_or_insert_with( &mut self, - func: impl FnOnce() -> T, - ) -> Mut<'_, T> { - if !self.contains_resource::() { + func: impl FnOnce() -> R, + ) -> Mut<'_, R> { + if !self.contains_resource::() { self.insert_resource(func()); } self.get_resource_mut().unwrap() @@ -766,16 +766,16 @@ impl World { /// This will allow aliased mutable access to the given resource type. The caller must ensure /// that only one mutable access exists at a time. #[inline] - pub unsafe fn get_resource_unchecked_mut(&self) -> Option> { - let component_id = self.components.get_resource_id(TypeId::of::())?; + pub unsafe fn get_resource_unchecked_mut(&self) -> Option> { + let component_id = self.components.get_resource_id(TypeId::of::())?; self.get_resource_unchecked_mut_with_id(component_id) } /// Gets a reference to the non-send resource of the given type, if it exists. /// Otherwise returns [None] #[inline] - pub fn get_non_send_resource(&self) -> Option<&T> { - let component_id = self.components.get_resource_id(TypeId::of::())?; + pub fn get_non_send_resource(&self) -> Option<&R> { + let component_id = self.components.get_resource_id(TypeId::of::())?; // SAFE: component id matches type T unsafe { self.get_non_send_with_id(component_id) } } @@ -783,7 +783,7 @@ impl World { /// Gets a mutable reference to the non-send resource of the given type, if it exists. /// Otherwise returns [None] #[inline] - pub fn get_non_send_resource_mut(&mut self) -> Option> { + pub fn get_non_send_resource_mut(&mut self) -> Option> { // SAFE: unique world access unsafe { self.get_non_send_resource_unchecked_mut() } } @@ -795,8 +795,8 @@ impl World { /// This will allow aliased mutable access to the given non-send resource type. The caller must /// ensure that only one mutable access exists at a time. #[inline] - pub unsafe fn get_non_send_resource_unchecked_mut(&self) -> Option> { - let component_id = self.components.get_resource_id(TypeId::of::())?; + pub unsafe fn get_non_send_resource_unchecked_mut(&self) -> Option> { + let component_id = self.components.get_resource_id(TypeId::of::())?; self.get_non_send_unchecked_mut_with_id(component_id) } @@ -946,22 +946,22 @@ impl World { /// }); /// assert_eq!(world.get_resource::().unwrap().0, 2); /// ``` - pub fn resource_scope(&mut self, f: impl FnOnce(&mut World, Mut) -> U) -> U { + pub fn resource_scope(&mut self, f: impl FnOnce(&mut World, Mut) -> U) -> U { let component_id = self .components - .get_resource_id(TypeId::of::()) - .unwrap_or_else(|| panic!("resource does not exist: {}", std::any::type_name::())); + .get_resource_id(TypeId::of::()) + .unwrap_or_else(|| panic!("resource does not exist: {}", std::any::type_name::())); let (ptr, mut ticks) = { let resource_archetype = self.archetypes.resource_mut(); let unique_components = resource_archetype.unique_components_mut(); let column = unique_components.get_mut(component_id).unwrap_or_else(|| { - panic!("resource does not exist: {}", std::any::type_name::()) + panic!("resource does not exist: {}", std::any::type_name::()) }); if column.is_empty() { - panic!("resource does not exist: {}", std::any::type_name::()); + panic!("resource does not exist: {}", std::any::type_name::()); } // SAFE: if a resource column exists, row 0 exists as well. caller takes ownership of - // the ptr value / drop is called when T is dropped + // the ptr value / drop is called when R is dropped unsafe { column.swap_remove_and_forget_unchecked(0) } }; // SAFE: pointer is of type T and valid to move out of @@ -1046,7 +1046,7 @@ impl World { } /// # Safety - /// `component_id` must be valid and correspond to a resource component of type T + /// `component_id` must be valid and correspond to a resource component of type R #[inline] unsafe fn insert_resource_with_id(&mut self, component_id: ComponentId, value: T) { let change_tick = self.change_tick(); @@ -1057,8 +1057,8 @@ impl World { let data = (&mut *value as *mut T).cast::(); column.push(data, ComponentTicks::new(change_tick)); } else { - // SAFE: column is of type T and has already been allocated - *column.get_data_unchecked(0).cast::() = value; + // SAFE: column is of type R and has already been allocated + *column.get_data_unchecked(0).cast::() = value; column.get_ticks_unchecked_mut(0).set_changed(change_tick); } } diff --git a/crates/bevy_log/src/lib.rs b/crates/bevy_log/src/lib.rs index c9e04cafde31f..8318880970788 100644 --- a/crates/bevy_log/src/lib.rs +++ b/crates/bevy_log/src/lib.rs @@ -133,7 +133,7 @@ impl Plugin for LogPlugin { } })) .build(); - app.world.insert_non_send(guard); + app.world.insert_non_send_resource(guard); chrome_layer }; diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index 147f633f2ede1..9aa84cb282028 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -226,7 +226,8 @@ pub fn winit_runner_with(mut app: App) { let mut event_loop = app.world.remove_non_send::>().unwrap(); let mut create_window_event_reader = ManualEventReader::::default(); let mut app_exit_event_reader = ManualEventReader::::default(); - app.world.insert_non_send(event_loop.create_proxy()); + app.world + .insert_non_send_resource(event_loop.create_proxy()); trace!("Entering winit event loop"); From ab75d45d3ad0cbbfcddea5e77790d554e52cd58a Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Sun, 21 Nov 2021 16:59:44 -0500 Subject: [PATCH 07/13] Docs typo Co-authored-by: Niklas Eicker --- crates/bevy_ecs/src/world/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index d8b50bf87505a..05eb5affa4d86 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -621,7 +621,7 @@ impl World { unsafe { self.insert_resource_with_id(component_id, value) }; } - /// Inserts a new resource with default values. + /// Inserts a new non-send resource with default values. /// /// If the resource already exists, nothing happens. /// From 9ee981d2715cac7c8a3ef5ffec6cfa669d354bce Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Mon, 22 Nov 2021 02:31:51 -0500 Subject: [PATCH 08/13] Doc suggestions from code review --- crates/bevy_ecs/src/world/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 05eb5affa4d86..311d98c5e8630 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -597,7 +597,7 @@ impl World { /// If the resource already exists, nothing happens. /// /// Uses the [`FromWorld`] trait to determine values, - /// which has a blanket impl for all `T: Default`. + /// which has a blanket impl for all `R: Default`. #[inline] pub fn init_resource(&mut self) { // PERF: We could avoid double hashing here, since the `from_resources` call is guaranteed @@ -612,8 +612,8 @@ impl World { /// Inserts a new resource with the given `value`. /// /// Resources are "unique" data of a given type. - /// Insert a resource of a type that already exists - /// will overwrite any existing data. + /// If you insert a resource of a type that already exists, + /// you will overwrite any existing data. #[inline] pub fn insert_resource(&mut self, value: T) { let component_id = self.components.init_resource::(); @@ -626,7 +626,7 @@ impl World { /// If the resource already exists, nothing happens. /// /// Uses the [`FromWorld`] trait to determine values, - /// which has a blanket impl for all `T: Default`. + /// which has a blanket impl for all `R: Default`. #[inline] pub fn init_non_send_resource(&mut self) { // PERF: We could avoid double hashing here, since the `from_resources` call is guaranteed From 2c00df2aba27a41dbeaa9c338103d711f53ca737 Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Mon, 22 Nov 2021 03:49:31 -0500 Subject: [PATCH 09/13] Docs clarity for init_resource --- crates/bevy_app/src/app.rs | 14 ++++++++------ crates/bevy_ecs/src/system/commands/mod.rs | 2 +- crates/bevy_ecs/src/world/mod.rs | 14 ++++++++------ 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 86f633df9bf7f..734ef502abd3a 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -673,11 +673,13 @@ impl App { self } - /// Initialize a resource with default values by adding it to the [`World`] + /// Initialize a resource with standard starting values by adding it to the [`World`] /// /// If the resource already exists, nothing happens. /// - /// The resource must implement either the `Default` or [`FromWorld`] trait. + /// The resource must implement the [`FromWorld`] trait. + /// If the `Default` trait is implemented, the `FromWorld` trait will use + /// the `Default::default` method to initialize the resource. /// /// ## Example /// ``` @@ -703,11 +705,11 @@ impl App { self } - /// Initialize a non-send resource with default values by adding it to the [`World`] + /// Initialize a non-send resource with standard starting values by adding it to the [`World`] /// - /// If the resource already exists, nothing happens. - /// - /// The resource must implement either the `Default` or [`FromWorld`] trait. + /// The resource must implement the [`FromWorld`] trait. + /// If the `Default` trait is implemented, the `FromWorld` trait will use + /// the `Default::default` method to initialize the resource. pub fn init_non_send_resource(&mut self) -> &mut Self { self.world.init_non_send_resource::(); self diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs index 78d5afad6b086..ad237367b0fe5 100644 --- a/crates/bevy_ecs/src/system/commands/mod.rs +++ b/crates/bevy_ecs/src/system/commands/mod.rs @@ -261,7 +261,7 @@ impl<'w, 's> Commands<'w, 's> { self.queue.push(InsertOrSpawnBatch { bundles_iter }); } - /// Inserts a resource with default values to the [`World`]. + /// Inserts a resource with standard starting values to the [`World`]. /// /// If the resource already exists, nothing happens. /// diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 311d98c5e8630..fa222d94311ed 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -592,12 +592,13 @@ impl World { } } - /// Inserts a new resource with default values. + /// Inserts a new resource with standard starting values. /// /// If the resource already exists, nothing happens. /// - /// Uses the [`FromWorld`] trait to determine values, - /// which has a blanket impl for all `R: Default`. + /// The value given by the [`FromWorld::from_world`] method will be used. + /// Note that any resource with the `Default` trait automatically implements `FromWorld`, + /// and those default values will be here instead. #[inline] pub fn init_resource(&mut self) { // PERF: We could avoid double hashing here, since the `from_resources` call is guaranteed @@ -621,12 +622,13 @@ impl World { unsafe { self.insert_resource_with_id(component_id, value) }; } - /// Inserts a new non-send resource with default values. + /// Inserts a new non-send resource with standard starting values. /// /// If the resource already exists, nothing happens. /// - /// Uses the [`FromWorld`] trait to determine values, - /// which has a blanket impl for all `R: Default`. + /// The value given by the [`FromWorld::from_world`] method will be used. + /// Note that any resource with the `Default` trait automatically implements `FromWorld`, + /// and those default values will be here instead. #[inline] pub fn init_non_send_resource(&mut self) { // PERF: We could avoid double hashing here, since the `from_resources` call is guaranteed From 95fe035589a00c8d49740add32f87d31b7f6d6fc Mon Sep 17 00:00:00 2001 From: Alice Date: Mon, 7 Feb 2022 23:27:52 -0500 Subject: [PATCH 10/13] Fix minor rebase issues --- crates/bevy_ecs/src/world/mod.rs | 60 ++++++++++++++++---------------- crates/bevy_winit/src/lib.rs | 5 ++- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index fa222d94311ed..578083c04d5fb 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -616,8 +616,8 @@ impl World { /// If you insert a resource of a type that already exists, /// you will overwrite any existing data. #[inline] - pub fn insert_resource(&mut self, value: T) { - let component_id = self.components.init_resource::(); + pub fn insert_resource(&mut self, value: R) { + let component_id = self.components.init_resource::(); // SAFE: component_id just initialized and corresponds to resource of type T unsafe { self.insert_resource_with_id(component_id, value) }; } @@ -968,7 +968,7 @@ impl World { }; // SAFE: pointer is of type T and valid to move out of // Read the value onto the stack to avoid potential mut aliasing. - let mut value = unsafe { std::ptr::read(ptr.cast::()) }; + let mut value = unsafe { std::ptr::read(ptr.cast::()) }; let value_mut = Mut { value: &mut value, ticks: Ticks { @@ -978,12 +978,12 @@ impl World { }, }; let result = f(self, value_mut); - assert!(!self.contains_resource::()); + assert!(!self.contains_resource::()); let resource_archetype = self.archetypes.resource_mut(); let unique_components = resource_archetype.unique_components_mut(); let column = unique_components .get_mut(component_id) - .unwrap_or_else(|| panic!("resource does not exist: {}", std::any::type_name::())); + .unwrap_or_else(|| panic!("resource does not exist: {}", std::any::type_name::())); // Wrap the value in MaybeUninit to prepare for passing the value back into the ECS let mut nodrop_wrapped_value = std::mem::MaybeUninit::new(value); @@ -995,27 +995,27 @@ impl World { } /// # Safety - /// `component_id` must be assigned to a component of type T + /// `component_id` must be assigned to a component of type `R` #[inline] - pub(crate) unsafe fn get_resource_with_id( + pub(crate) unsafe fn get_resource_with_id( &self, component_id: ComponentId, - ) -> Option<&T> { + ) -> Option<&R> { let column = self.get_populated_resource_column(component_id)?; - Some(&*column.get_data_ptr().as_ptr().cast::()) + Some(&*column.get_data_ptr().as_ptr().cast::()) } /// # Safety - /// `component_id` must be assigned to a component of type T. + /// `component_id` must be assigned to a component of type `R` /// Caller must ensure this doesn't violate Rust mutability rules for the given resource. #[inline] - pub(crate) unsafe fn get_resource_unchecked_mut_with_id( + pub(crate) unsafe fn get_resource_unchecked_mut_with_id( &self, component_id: ComponentId, - ) -> Option> { + ) -> Option> { let column = self.get_populated_resource_column(component_id)?; Some(Mut { - value: &mut *column.get_data_ptr().cast::().as_ptr(), + value: &mut *column.get_data_ptr().cast::().as_ptr(), ticks: Ticks { component_ticks: &mut *column.get_ticks_mut_ptr_unchecked(0), last_change_tick: self.last_change_tick(), @@ -1025,38 +1025,38 @@ impl World { } /// # Safety - /// `component_id` must be assigned to a component of type T + /// `component_id` must be assigned to a component of type `R` #[inline] - pub(crate) unsafe fn get_non_send_with_id( + pub(crate) unsafe fn get_non_send_with_id( &self, component_id: ComponentId, - ) -> Option<&T> { - self.validate_non_send_access::(); + ) -> Option<&R> { + self.validate_non_send_access::(); self.get_resource_with_id(component_id) } /// # Safety - /// `component_id` must be assigned to a component of type T. + /// `component_id` must be assigned to a component of type `R`. /// Caller must ensure this doesn't violate Rust mutability rules for the given resource. #[inline] - pub(crate) unsafe fn get_non_send_unchecked_mut_with_id( + pub(crate) unsafe fn get_non_send_unchecked_mut_with_id( &self, component_id: ComponentId, - ) -> Option> { - self.validate_non_send_access::(); + ) -> Option> { + self.validate_non_send_access::(); self.get_resource_unchecked_mut_with_id(component_id) } /// # Safety - /// `component_id` must be valid and correspond to a resource component of type R + /// `component_id` must be valid and correspond to a resource component of type `R` #[inline] - unsafe fn insert_resource_with_id(&mut self, component_id: ComponentId, value: T) { + unsafe fn insert_resource_with_id(&mut self, component_id: ComponentId, value: R) { let change_tick = self.change_tick(); let column = self.initialize_resource_internal(component_id); if column.is_empty() { let mut value = ManuallyDrop::new(value); - // SAFE: column is of type T and has been allocated above - let data = (&mut *value as *mut T).cast::(); + // SAFE: column is of type R and has been allocated above + let data = (&mut *value as *mut R).cast::(); column.push(data, ComponentTicks::new(change_tick)); } else { // SAFE: column is of type R and has already been allocated @@ -1066,7 +1066,7 @@ impl World { } /// # Safety - /// `component_id` must be valid and correspond to a resource component of type T + /// `component_id` must be valid and correspond to a resource component of type `R` #[inline] unsafe fn initialize_resource_internal(&mut self, component_id: ComponentId) -> &mut Column { // SAFE: resource archetype always exists @@ -1095,15 +1095,15 @@ impl World { }) } - pub(crate) fn initialize_resource(&mut self) -> ComponentId { - let component_id = self.components.init_resource::(); + pub(crate) fn initialize_resource(&mut self) -> ComponentId { + let component_id = self.components.init_resource::(); // SAFE: resource initialized above unsafe { self.initialize_resource_internal(component_id) }; component_id } - pub(crate) fn initialize_non_send_resource(&mut self) -> ComponentId { - let component_id = self.components.init_non_send::(); + pub(crate) fn initialize_non_send_resource(&mut self) -> ComponentId { + let component_id = self.components.init_non_send::(); // SAFE: resource initialized above unsafe { self.initialize_resource_internal(component_id) }; component_id diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index 9aa84cb282028..3bab7128d4d02 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -223,7 +223,10 @@ pub fn winit_runner(app: App) { // } pub fn winit_runner_with(mut app: App) { - let mut event_loop = app.world.remove_non_send::>().unwrap(); + let mut event_loop = app + .world + .remove_non_send_resource::>() + .unwrap(); let mut create_window_event_reader = ManualEventReader::::default(); let mut app_exit_event_reader = ManualEventReader::::default(); app.world From 77c0287a5598e198f7e695f65217e202f5f57144 Mon Sep 17 00:00:00 2001 From: Alice Date: Mon, 7 Feb 2022 23:41:14 -0500 Subject: [PATCH 11/13] Missing doc backticks --- crates/bevy_ecs/src/world/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 578083c04d5fb..5dcec85c7ebb9 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -642,7 +642,7 @@ impl World { /// Inserts a new non-send resource with the given `value`. /// - /// NonSend resources cannot be sent across threads, + /// `NonSend` resources cannot be sent across threads, /// and do not need the `Send + Sync` bounds. /// Systems with `NonSend` resources are always scheduled on the main thread. #[inline] @@ -669,7 +669,7 @@ impl World { #[inline] /// # Safety - /// Only remove NonSend resources from the main thread + /// Only remove `NonSend` resources from the main thread /// as they cannot be sent across theads #[allow(unused_unsafe)] pub unsafe fn remove_resource_unchecked(&mut self) -> Option { From d18942922de7b9e1cee6137336bf1a010bd9f45b Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Tue, 8 Feb 2022 11:03:24 -0500 Subject: [PATCH 12/13] Update crates/bevy_ecs/src/world/mod.rs Co-authored-by: bjorn3 --- crates/bevy_ecs/src/world/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 5dcec85c7ebb9..4e51256ecb9aa 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -601,7 +601,7 @@ impl World { /// and those default values will be here instead. #[inline] pub fn init_resource(&mut self) { - // PERF: We could avoid double hashing here, since the `from_resources` call is guaranteed + // PERF: We could avoid double hashing here, since the `from_world` call is guaranteed // not to modify the map. However, we would need to be borrowing resources both // mutably and immutably, so we would need to be extremely certain this is correct if !self.contains_resource::() { From 4e0950cd7c82014156b928c70a9c05559e1c2121 Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Tue, 8 Feb 2022 11:03:32 -0500 Subject: [PATCH 13/13] Update crates/bevy_ecs/src/world/mod.rs Co-authored-by: bjorn3 --- crates/bevy_ecs/src/world/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 4e51256ecb9aa..d1404c9df2072 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -631,7 +631,7 @@ impl World { /// and those default values will be here instead. #[inline] pub fn init_non_send_resource(&mut self) { - // PERF: We could avoid double hashing here, since the `from_resources` call is guaranteed + // PERF: We could avoid double hashing here, since the `from_world` call is guaranteed // not to modify the map. However, we would need to be borrowing resources both // mutably and immutably, so we would need to be extremely certain this is correct if !self.contains_resource::() {