diff --git a/CHANGELOG.md b/CHANGELOG.md index 8990788f..86795aeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Unreleased ### Changed +- Many generic methods that previously took a `Component` now instead take either a + `ComponentRef<'a>` or a `Query` to improve consistency with queries and address a common footgun: + - `World::get` and `EntityRef::get` now take shared or unique references to component types - `SerializeContext` traits now take their serializer arguments by value, and must call `end()` themselves. diff --git a/README.md b/README.md index 654370cf..e96c222d 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,8 @@ for (id, (number, &flag)) in world.query_mut::<(&mut i32, &bool)>() { if flag { *number *= 2; } } // Random access is simple and safe -assert_eq!(*world.get::(a).unwrap(), 246); -assert_eq!(*world.get::(b).unwrap(), 42); +assert_eq!(*world.get::<&i32>(a).unwrap(), 246); +assert_eq!(*world.get::<&i32>(b).unwrap(), 42); ``` ### Why ECS? diff --git a/examples/ffa_simulation.rs b/examples/ffa_simulation.rs index f25de0b7..835f427a 100644 --- a/examples/ffa_simulation.rs +++ b/examples/ffa_simulation.rs @@ -102,7 +102,7 @@ fn system_fire_at_closest(world: &mut World) { */ // Or like this: - let mut hp1 = world.get_mut::(closest).unwrap(); + let mut hp1 = world.get::<&mut Health>(closest).unwrap(); // Is target unit still alive? if hp1.0 > 0 { diff --git a/examples/format.rs b/examples/format.rs index e6d44642..055c5a51 100644 --- a/examples/format.rs +++ b/examples/format.rs @@ -3,7 +3,7 @@ fn format_entity(entity: hecs::EntityRef<'_>) -> String { fn fmt(entity: hecs::EntityRef<'_>) -> Option { - Some(entity.get::()?.to_string()) + Some(entity.get::<&T>()?.to_string()) } const FUNCTIONS: &[&dyn Fn(hecs::EntityRef<'_>) -> Option] = diff --git a/src/command_buffer.rs b/src/command_buffer.rs index d85b7bfa..5ab2d751 100644 --- a/src/command_buffer.rs +++ b/src/command_buffer.rs @@ -26,7 +26,7 @@ use crate::{Bundle, Entity}; /// let mut cmd = CommandBuffer::new(); /// cmd.insert(entity, (true, 42)); /// cmd.run_on(&mut world); // cmd can now be reused -/// assert_eq!(*world.get::(entity).unwrap(), 42); +/// assert_eq!(*world.get::<&i32>(entity).unwrap(), 42); /// ``` pub struct CommandBuffer { entities: Vec, diff --git a/src/entity_builder.rs b/src/entity_builder.rs index 4bf5c05d..3b6935af 100644 --- a/src/entity_builder.rs +++ b/src/entity_builder.rs @@ -26,8 +26,8 @@ use crate::{align, Component, DynamicBundle}; /// let mut builder = EntityBuilder::new(); /// builder.add(123).add("abc"); /// let e = world.spawn(builder.build()); // builder can now be reused -/// assert_eq!(*world.get::(e).unwrap(), 123); -/// assert_eq!(*world.get::<&str>(e).unwrap(), "abc"); +/// assert_eq!(*world.get::<&i32>(e).unwrap(), 123); +/// assert_eq!(*world.get::<&&str>(e).unwrap(), "abc"); /// ``` #[derive(Default)] pub struct EntityBuilder { @@ -142,10 +142,10 @@ impl Drop for BuiltEntity<'_> { /// let bundle = builder.build(); /// let e = world.spawn(&bundle); /// let f = world.spawn(&bundle); // `&bundle` can be used many times -/// assert_eq!(*world.get::(e).unwrap(), 123); -/// assert_eq!(*world.get::<&str>(e).unwrap(), "abc"); -/// assert_eq!(*world.get::(f).unwrap(), 123); -/// assert_eq!(*world.get::<&str>(f).unwrap(), "abc"); +/// assert_eq!(*world.get::<&i32>(e).unwrap(), 123); +/// assert_eq!(*world.get::<&&str>(e).unwrap(), "abc"); +/// assert_eq!(*world.get::<&i32>(f).unwrap(), 123); +/// assert_eq!(*world.get::<&&str>(f).unwrap(), "abc"); /// ``` #[derive(Clone, Default)] pub struct EntityBuilderClone { diff --git a/src/entity_ref.rs b/src/entity_ref.rs index 1db5326f..87f85241 100644 --- a/src/entity_ref.rs +++ b/src/entity_ref.rs @@ -33,19 +33,24 @@ impl<'a> EntityRef<'a> { self.archetype.has::() } - /// Borrow the component of type `T`, if it exists + /// Borrow a single component, if it exists /// - /// Panics if the component is already uniquely borrowed from another entity with the same - /// components. - pub fn get(&self) -> Option> { - Some(unsafe { Ref::new(self.archetype, self.index).ok()? }) - } - - /// Uniquely borrow the component of type `T`, if it exists + /// `T` must be a shared or unique reference to a component type. + /// + /// # Example + /// ``` + /// # use hecs::*; + /// let mut world = World::new(); + /// let a = world.spawn((42, "abc")); + /// let e = world.entity(a).unwrap(); + /// *e.get::<&mut i32>().unwrap() = 17; + /// assert_eq!(*e.get::<&i32>().unwrap(), 17); + /// ``` /// - /// Panics if the component is already borrowed from another entity with the same components. - pub fn get_mut(&self) -> Option> { - Some(unsafe { RefMut::new(self.archetype, self.index).ok()? }) + /// Panics if `T` is a unique reference and the component is already borrowed, or if the + /// component is already uniquely borrowed. + pub fn get>(&self) -> Option { + T::get_component(*self) } /// Run a query against this entity @@ -184,3 +189,40 @@ impl<'a, T: Component> DerefMut for RefMut<'a, T> { unsafe { self.target.as_mut() } } } + +/// `&T` or `&mut T` where `T` is some component type +/// +/// The interface of this trait is a private implementation detail. +pub trait ComponentRef<'a> { + /// Smart pointer to a component of the referenced type + #[doc(hidden)] + type Ref; + + /// Component type referenced by `Ref` + #[doc(hidden)] + type Component: Component; + + /// Fetch the component from `entity` + #[doc(hidden)] + fn get_component(entity: EntityRef<'a>) -> Option; +} + +impl<'a, T: Component> ComponentRef<'a> for &'a T { + type Ref = Ref<'a, T>; + + type Component = T; + + fn get_component(entity: EntityRef<'a>) -> Option { + Some(unsafe { Ref::new(entity.archetype, entity.index).ok()? }) + } +} + +impl<'a, T: Component> ComponentRef<'a> for &'a mut T { + type Ref = RefMut<'a, T>; + + type Component = T; + + fn get_component(entity: EntityRef<'a>) -> Option { + Some(unsafe { RefMut::new(entity.archetype, entity.index).ok()? }) + } +} diff --git a/src/lib.rs b/src/lib.rs index 95f1db1c..cbd24f93 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,8 +28,8 @@ //! if flag { *number *= 2; } //! } //! // Random access is simple and safe -//! assert_eq!(*world.get::(a).unwrap(), 246); -//! assert_eq!(*world.get::(b).unwrap(), 42); +//! assert_eq!(*world.get::<&i32>(a).unwrap(), 246); +//! assert_eq!(*world.get::<&i32>(b).unwrap(), 42); //! ``` #![warn(missing_docs)] @@ -79,7 +79,7 @@ pub use column::{Column, ColumnMut}; pub use command_buffer::CommandBuffer; pub use entities::{Entity, NoSuchEntity}; pub use entity_builder::{BuiltEntity, BuiltEntityClone, EntityBuilder, EntityBuilderClone}; -pub use entity_ref::{EntityRef, Ref, RefMut}; +pub use entity_ref::{ComponentRef, EntityRef, Ref, RefMut}; pub use query::{ Access, Batch, BatchedIter, Or, PreparedQuery, PreparedQueryBorrow, PreparedQueryIter, PreparedView, Query, QueryBorrow, QueryItem, QueryIter, QueryMut, QueryShared, Satisfies, View, diff --git a/src/serialize/column.rs b/src/serialize/column.rs index 1b1d3bb9..35ab65fc 100644 --- a/src/serialize/column.rs +++ b/src/serialize/column.rs @@ -757,7 +757,7 @@ mod tests { impl PartialEq for SerWorld { fn eq(&self, other: &Self) -> bool { fn same_components(x: &EntityRef, y: &EntityRef) -> bool { - x.get::().as_ref().map(|x| &**x) == y.get::().as_ref().map(|x| &**x) + x.get::<&T>().as_ref().map(|x| &**x) == y.get::<&T>().as_ref().map(|x| &**x) } for (x, y) in self.0.iter().zip(other.0.iter()) { @@ -779,8 +779,8 @@ mod tests { ( e.entity(), ( - e.get::().map(|x| *x), - e.get::().map(|x| *x), + e.get::<&Position>().map(|x| *x), + e.get::<&Velocity>().map(|x| *x), ), ) })) diff --git a/src/serialize/row.rs b/src/serialize/row.rs index cbbebebc..6495d29f 100644 --- a/src/serialize/row.rs +++ b/src/serialize/row.rs @@ -82,7 +82,7 @@ pub fn try_serialize Result<(), S::Error> { - if let Some(x) = entity.get::() { + if let Some(x) = entity.get::<&T>() { map.serialize_key(key)?; map.serialize_value(&*x)?; } @@ -270,7 +270,7 @@ mod tests { impl PartialEq for SerWorld { fn eq(&self, other: &Self) -> bool { fn same_components(x: &EntityRef, y: &EntityRef) -> bool { - x.get::().as_ref().map(|x| &**x) == y.get::().as_ref().map(|x| &**x) + x.get::<&T>().as_ref().map(|x| &**x) == y.get::<&T>().as_ref().map(|x| &**x) } for (x, y) in self.0.iter().zip(other.0.iter()) { @@ -292,8 +292,8 @@ mod tests { ( e.entity(), ( - e.get::().map(|x| *x), - e.get::().map(|x| *x), + e.get::<&Position>().map(|x| *x), + e.get::<&Velocity>().map(|x| *x), ), ) })) diff --git a/src/world.rs b/src/world.rs index 878503a8..dcc8e486 100644 --- a/src/world.rs +++ b/src/world.rs @@ -24,9 +24,8 @@ use crate::alloc::boxed::Box; use crate::archetype::{Archetype, TypeIdMap, TypeInfo}; use crate::entities::{Entities, EntityMeta, Location, ReserveEntitiesIterator}; use crate::{ - Bundle, Column, ColumnBatch, ColumnMut, DynamicBundle, Entity, EntityRef, Fetch, - MissingComponent, NoSuchEntity, Query, QueryBorrow, QueryItem, QueryMut, QueryOne, Ref, RefMut, - TakenEntity, + Bundle, Column, ColumnBatch, ColumnMut, ComponentRef, DynamicBundle, Entity, EntityRef, Fetch, + MissingComponent, NoSuchEntity, Query, QueryBorrow, QueryItem, QueryMut, QueryOne, TakenEntity, }; /// An unordered collection of entities, each having any number of distinctly typed components @@ -187,7 +186,7 @@ impl World { /// let mut world = World::new(); /// let entities = world.spawn_batch((0..1_000).map(|i| (i, "abc"))).collect::>(); /// for i in 0..1_000 { - /// assert_eq!(*world.get::(entities[i]).unwrap(), i as i32); + /// assert_eq!(*world.get::<&i32>(entities[i]).unwrap(), i as i32); /// } /// ``` pub fn spawn_batch(&mut self, iter: I) -> SpawnBatchIter<'_, I::IntoIter> @@ -469,25 +468,15 @@ impl World { unsafe { Ok(fetch.get(loc.index as usize)) } } - /// Borrow the `T` component of `entity` - /// - /// Panics if the component is already uniquely borrowed from another entity with the same - /// components. - pub fn get(&self, entity: Entity) -> Result, ComponentError> { - Ok(self - .entity(entity)? - .get() - .ok_or_else(MissingComponent::new::)?) - } - - /// Uniquely borrow the `T` component of `entity` - /// - /// Panics if the component is already borrowed from another entity with the same components. - pub fn get_mut(&self, entity: Entity) -> Result, ComponentError> { + /// Short-hand for [`entity`](Self::entity) followed by [`EntityRef::get`] + pub fn get<'a, T: ComponentRef<'a>>( + &'a self, + entity: Entity, + ) -> Result { Ok(self .entity(entity)? - .get_mut() - .ok_or_else(MissingComponent::new::)?) + .get::() + .ok_or_else(MissingComponent::new::)?) } /// Access an entity regardless of its component types @@ -547,8 +536,8 @@ impl World { /// let mut world = World::new(); /// let e = world.spawn((123, "abc")); /// world.insert(e, (456, true)); - /// assert_eq!(*world.get::(e).unwrap(), 456); - /// assert_eq!(*world.get::(e).unwrap(), true); + /// assert_eq!(*world.get::<&i32>(e).unwrap(), 456); + /// assert_eq!(*world.get::<&bool>(e).unwrap(), true); /// ``` pub fn insert( &mut self, @@ -666,9 +655,9 @@ impl World { /// let mut world = World::new(); /// let e = world.spawn((123, "abc", true)); /// assert_eq!(world.remove::<(i32, &str)>(e), Ok((123, "abc"))); - /// assert!(world.get::(e).is_err()); - /// assert!(world.get::<&str>(e).is_err()); - /// assert_eq!(*world.get::(e).unwrap(), true); + /// assert!(world.get::<&i32>(e).is_err()); + /// assert!(world.get::<&&str>(e).is_err()); + /// assert_eq!(*world.get::<&bool>(e).unwrap(), true); /// ``` pub fn remove(&mut self, entity: Entity) -> Result { self.flush(); @@ -1389,13 +1378,13 @@ mod tests { fn reuse_populated() { let mut world = World::new(); let a = world.spawn((42,)); - assert_eq!(*world.get::(a).unwrap(), 42); + assert_eq!(*world.get::<&i32>(a).unwrap(), 42); world.despawn(a).unwrap(); let b = world.spawn((true,)); assert_eq!(a.id, b.id); assert_ne!(a.generation, b.generation); - assert!(world.get::(b).is_err()); - assert!(*world.get::(b).unwrap()); + assert!(world.get::<&i32>(b).is_err()); + assert!(*world.get::<&bool>(b).unwrap()); } #[test] diff --git a/tests/tests.rs b/tests/tests.rs index 44354c97..f69b7338 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -15,12 +15,12 @@ fn random_access() { let mut world = World::new(); let e = world.spawn(("abc", 123)); let f = world.spawn(("def", 456, true)); - assert_eq!(*world.get::<&str>(e).unwrap(), "abc"); - assert_eq!(*world.get::(e).unwrap(), 123); - assert_eq!(*world.get::<&str>(f).unwrap(), "def"); - assert_eq!(*world.get::(f).unwrap(), 456); - *world.get_mut::(f).unwrap() = 42; - assert_eq!(*world.get::(f).unwrap(), 42); + assert_eq!(*world.get::<&&str>(e).unwrap(), "abc"); + assert_eq!(*world.get::<&i32>(e).unwrap(), 123); + assert_eq!(*world.get::<&&str>(f).unwrap(), "def"); + assert_eq!(*world.get::<&i32>(f).unwrap(), 456); + *world.get::<&mut i32>(f).unwrap() = 42; + assert_eq!(*world.get::<&i32>(f).unwrap(), 42); } #[test] @@ -31,10 +31,10 @@ fn despawn() { assert_eq!(world.query::<()>().iter().count(), 2); world.despawn(e).unwrap(); assert_eq!(world.query::<()>().iter().count(), 1); - assert!(world.get::<&str>(e).is_err()); - assert!(world.get::(e).is_err()); - assert_eq!(*world.get::<&str>(f).unwrap(), "def"); - assert_eq!(*world.get::(f).unwrap(), 456); + assert!(world.get::<&&str>(e).is_err()); + assert!(world.get::<&i32>(e).is_err()); + assert_eq!(*world.get::<&&str>(f).unwrap(), "def"); + assert_eq!(*world.get::<&i32>(f).unwrap(), 456); } #[test] @@ -282,10 +282,10 @@ fn build_entity() { entity.add(456); entity.add(789); let f = world.spawn(entity.build()); - assert_eq!(*world.get::<&str>(e).unwrap(), "abc"); - assert_eq!(*world.get::(e).unwrap(), 123); - assert_eq!(*world.get::<&str>(f).unwrap(), "def"); - assert_eq!(*world.get::(f).unwrap(), 789); + assert_eq!(*world.get::<&&str>(e).unwrap(), "abc"); + assert_eq!(*world.get::<&i32>(e).unwrap(), 123); + assert_eq!(*world.get::<&&str>(f).unwrap(), "def"); + assert_eq!(*world.get::<&i32>(f).unwrap(), 789); } #[test] @@ -308,14 +308,14 @@ fn build_entity_clone() { .unwrap(); for e in [e, f, g] { - assert_eq!(*world.get::<&str>(e).unwrap(), "yup"); - assert_eq!(*world.get::(e).unwrap(), 789); - assert_eq!(*world.get::(e).unwrap(), 42); - assert_eq!(*world.get::(e).unwrap(), 7.0); - assert_eq!(*world.get::(e).unwrap(), "Bar"); + assert_eq!(*world.get::<&&str>(e).unwrap(), "yup"); + assert_eq!(*world.get::<&i32>(e).unwrap(), 789); + assert_eq!(*world.get::<&usize>(e).unwrap(), 42); + assert_eq!(*world.get::<&f32>(e).unwrap(), 7.0); + assert_eq!(*world.get::<&String>(e).unwrap(), "Bar"); } - assert_eq!(*world.get::>(g).unwrap(), "after"); + assert_eq!(*world.get::<&Cow<'static, str>>(g).unwrap(), "after"); } #[test] @@ -337,8 +337,8 @@ fn cloned_builder() { let mut world = World::new(); let e = world.spawn(&builder.build().clone()); - assert_eq!(*world.get::(e).unwrap(), "abc"); - assert_eq!(*world.get::(e).unwrap(), 123); + assert_eq!(*world.get::<&String>(e).unwrap(), "abc"); + assert_eq!(*world.get::<&i32>(e).unwrap(), 123); } #[test] @@ -365,13 +365,13 @@ fn build_dynamic_bundle() { .unwrap(); for e in [e, f, g] { - assert_eq!(*world.get::(e).unwrap(), 5); - assert_eq!(*world.get::(e).unwrap(), 'a'); - assert_eq!(*world.get::(e).unwrap(), "Bar"); - assert_eq!(*world.get::(e).unwrap(), 6.0); + assert_eq!(*world.get::<&i32>(e).unwrap(), 5); + assert_eq!(*world.get::<&char>(e).unwrap(), 'a'); + assert_eq!(*world.get::<&String>(e).unwrap(), "Bar"); + assert_eq!(*world.get::<&f32>(e).unwrap(), 6.0); } - assert_eq!(*world.get::>(g).unwrap(), "after"); + assert_eq!(*world.get::<&Cow<'static, str>>(g).unwrap(), "after"); } #[test] @@ -395,8 +395,8 @@ fn access_builder_components() { let g = world.spawn(entity.build()); - assert_eq!(*world.get::<&str>(g).unwrap(), "abc"); - assert_eq!(*world.get::(g).unwrap(), 456); + assert_eq!(*world.get::<&&str>(g).unwrap(), "abc"); + assert_eq!(*world.get::<&i32>(g).unwrap(), 456); } #[test] @@ -408,10 +408,10 @@ fn build_entity_bundle() { entity.add(456); entity.add_bundle(("def", [0u8; 1024], 789)); let f = world.spawn(entity.build()); - assert_eq!(*world.get::<&str>(e).unwrap(), "abc"); - assert_eq!(*world.get::(e).unwrap(), 123); - assert_eq!(*world.get::<&str>(f).unwrap(), "def"); - assert_eq!(*world.get::(f).unwrap(), 789); + assert_eq!(*world.get::<&&str>(e).unwrap(), "abc"); + assert_eq!(*world.get::<&i32>(e).unwrap(), 123); + assert_eq!(*world.get::<&&str>(f).unwrap(), "def"); + assert_eq!(*world.get::<&i32>(f).unwrap(), 789); } #[test] @@ -462,11 +462,11 @@ fn spawn_buffered_entity() { buffer.run_on(&mut world); - assert_eq!(*world.get::(ent).unwrap(), true); - assert_eq!(*world.get::<&str>(ent1).unwrap(), "hecs"); - assert_eq!(*world.get::(ent1).unwrap(), 13); - assert_eq!(*world.get::(ent2).unwrap(), false); - assert_eq!(*world.get::(ent3).unwrap(), 2); + assert_eq!(*world.get::<&bool>(ent).unwrap(), true); + assert_eq!(*world.get::<&&str>(ent1).unwrap(), "hecs"); + assert_eq!(*world.get::<&i32>(ent1).unwrap(), 13); + assert_eq!(*world.get::<&bool>(ent2).unwrap(), false); + assert_eq!(*world.get::<&u8>(ent3).unwrap(), 2); } #[test] @@ -489,8 +489,8 @@ fn remove_buffered_component() { buffer.remove::<(i32, &str)>(ent); buffer.run_on(&mut world); - assert!(world.get::<&str>(ent).is_err()); - assert!(world.get::(ent).is_err()); + assert!(world.get::<&&str>(ent).is_err()); + assert!(world.get::<&i32>(ent).is_err()); } #[test] @@ -547,8 +547,8 @@ fn shared_borrow() { fn illegal_random_access() { let mut world = World::new(); let e = world.spawn(("abc", 123)); - let _borrow = world.get_mut::(e).unwrap(); - world.get::(e).unwrap(); + let _borrow = world.get::<&mut i32>(e).unwrap(); + world.get::<&i32>(e).unwrap(); } #[test] @@ -562,8 +562,8 @@ fn derived_bundle() { let mut world = World::new(); let e = world.spawn(Foo { x: 42, y: 'a' }); - assert_eq!(*world.get::(e).unwrap(), 42); - assert_eq!(*world.get::(e).unwrap(), 'a'); + assert_eq!(*world.get::<&i32>(e).unwrap(), 42); + assert_eq!(*world.get::<&char>(e).unwrap(), 'a'); } #[test] @@ -623,14 +623,14 @@ fn exchange_components() { let mut world = World::new(); let entity = world.spawn(("abc".to_owned(), 123)); - assert!(world.get::(entity).is_ok()); - assert!(world.get::(entity).is_ok()); - assert!(world.get::(entity).is_err()); + assert!(world.get::<&String>(entity).is_ok()); + assert!(world.get::<&i32>(entity).is_ok()); + assert!(world.get::<&bool>(entity).is_err()); world.exchange_one::(entity, true).unwrap(); - assert!(world.get::(entity).is_err()); - assert!(world.get::(entity).is_ok()); - assert!(world.get::(entity).is_ok()); + assert!(world.get::<&String>(entity).is_err()); + assert!(world.get::<&i32>(entity).is_ok()); + assert!(world.get::<&bool>(entity).is_ok()); } #[test] @@ -772,9 +772,9 @@ fn spawn_column_batch() { .spawn_column_batch(batch.build().unwrap()) .collect::>(); assert_eq!(entities.len(), 2); - assert_eq!(*world.get::(b).unwrap(), 43); - assert_eq!(*world.get::(entities[0]).unwrap(), 44); - assert_eq!(*world.get::(entities[1]).unwrap(), 45); + assert_eq!(*world.get::<&i32>(b).unwrap(), 43); + assert_eq!(*world.get::<&i32>(entities[0]).unwrap(), 44); + assert_eq!(*world.get::<&i32>(entities[1]).unwrap(), 45); } } @@ -840,7 +840,7 @@ fn column_get_mut() { *column.get(ent).unwrap() = 99; assert_eq!(*column.get(ent).unwrap(), 99); } - assert_eq!(*world.get::(ent).unwrap(), 99); + assert_eq!(*world.get::<&i32>(ent).unwrap(), 99); } #[test] @@ -864,10 +864,10 @@ fn take() { let mut world_b = World::new(); let e2 = world_b.spawn(world_a.take(e).unwrap()); assert!(!world_a.contains(e)); - assert_eq!(*world_b.get::(e2).unwrap(), "abc"); - assert_eq!(*world_b.get::(e2).unwrap(), 42); - assert_eq!(*world_a.get::(f).unwrap(), "def"); - assert_eq!(*world_a.get::(f).unwrap(), 17); + assert_eq!(*world_b.get::<&String>(e2).unwrap(), "abc"); + assert_eq!(*world_b.get::<&i32>(e2).unwrap(), 42); + assert_eq!(*world_a.get::<&String>(f).unwrap(), "def"); + assert_eq!(*world_a.get::<&i32>(f).unwrap(), 17); world_b.take(e2).unwrap(); assert!(!world_b.contains(e2)); }