Repository: Ralith/hecs
Pull request #274 (2022-07-11 05:13:44)

Refactor World::get to take reference types
Many users have reported confusion arising from the use of component types in `World::get` in contrast to the use of reference sin `World::query` and friends. This replaces `get` and `get_mut` on `World` and `EntityRef` with a single `get` that is generic over *references to components*, so that the intuitive thing Just Works, and passing an explicit component type generates a trait error.

For consistency, `EntityBuilder:;get` and `get_mut` are both refactored similarly, although they cannot be combined into a single method as they do not perform dynamic borrow checking.

This also resolves the inconsistency between `get_mut` referring to the mutability of the component borrow, while other `_mut` methods on `World` instead refer to the mutability of the world borrow.

adamreichold: I have not formed an opinion of whether this simplifies explaining things (In my mental model, `World::get(_mut)` were the primitives out of which the queries are built via their DSL.), I wanted to add that the query combinators potentially have a similar foot gun, e.g. `Query<With<(&R, &S), &T>>` does not work as one might expect and the correct `Query<With<(&R, &S), T>>` might be surprising. (I guess it isn't completely the same as `&T` and `&mut T` imply no difference for the query combinator.) 
Ralith: I've received many independent user reports of footgun-related injuries here, so I'm convinced of the benefit.

`With`/`Without` are an interesting point. I've also been a bit unhappy with how they have to be nested to consider multiple components. Maybe we should refactor those to operate on two queries, rather than a query and a component type? Logically equivalent to the 2-tuple combinator, except that the results for the second item are not yielded (or borrowed).
adamreichold: > Maybe we should refactor those to operate on two queries, rather than a query and a component type?

This sounds sensible and would also be nicely consistent with `Satisfies`.

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8990788..6b59bbf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,18 @@
 # Unreleased
 
+### Added
+- `World::satisfies` and `EntityRef::satisfies` to check if an entity would match a query
+
 ### 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`, `EntityRef::get`, and `Archetype::get` now take shared or unique references to
+    component types
+  - `EntityBuilder` and `EntityBuilderClone`'s `get` and `get_mut` refactored along the same lines
+    for consistency
+  - The `With`/`Without` query transformers now take a query that entities must/mustn't match rather
+    than a component type. Additionally, the order of their generic arguments was reversed to place
+    the query whose results will be yielded first.
 - `SerializeContext` traits now take their serializer arguments by value, and must call `end()`
   themselves.
 
diff --git a/README.md b/README.md
index 654370c..e96c222 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::<i32>(a).unwrap(), 246);
-assert_eq!(*world.get::<i32>(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 f25de0b..44f3c13 100644
--- a/examples/ffa_simulation.rs
+++ b/examples/ffa_simulation.rs
@@ -73,14 +73,14 @@ fn system_integrate_motion(world: &mut World, query: &mut PreparedQuery<(&mut Po
 // In this system entities find the closest entity and fire at them
 fn system_fire_at_closest(world: &mut World) {
     for (id0, (pos0, dmg0, kc0)) in
-        &mut world.query::<With<Health, (&Position, &Damage, &mut KillCount)>>()
+        &mut world.query::<With<(&Position, &Damage, &mut KillCount), &Health>>()
     {
         // Find closest:
         // Nested queries are O(n^2) and you usually want to avoid that by using some sort of
         // spatial index like a quadtree or more general BVH, which we don't bother with here since
         // it's out of scope for the example.
         let closest = world
-            .query::<With<Health, &Position>>()
+            .query::<With<&Position, &Health>>()
             .iter()
             .filter(|(id1, _)| *id1 != id0)
             .min_by_key(|(_, pos1)| manhattan_dist(pos0.x, pos1.x, pos0.y, pos1.y))
@@ -102,7 +102,7 @@ fn system_fire_at_closest(world: &mut World) {
         */
 
         // Or like this:
-        let mut hp1 = world.get_mut::<Health>(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 e6d4464..055c5a5 100644
--- a/examples/format.rs
+++ b/examples/format.rs
@@ -3,7 +3,7 @@
 
 fn format_entity(entity: hecs::EntityRef<'_>) -> String {
     fn fmt<T: hecs::Component + std::fmt::Display>(entity: hecs::EntityRef<'_>) -> Option<String> {
-        Some(entity.get::<T>()?.to_string())
+        Some(entity.get::<&T>()?.to_string())
     }
 
     const FUNCTIONS: &[&dyn Fn(hecs::EntityRef<'_>) -> Option<String>] =
diff --git a/src/archetype.rs b/src/archetype.rs
index 95bfb42..ee89d3e 100644
--- a/src/archetype.rs
+++ b/src/archetype.rs
@@ -9,16 +9,16 @@ use crate::alloc::alloc::{alloc, dealloc, Layout};
 use crate::alloc::boxed::Box;
 use crate::alloc::{vec, vec::Vec};
 use core::any::{type_name, TypeId};
+use core::fmt;
 use core::hash::{BuildHasher, BuildHasherDefault, Hasher};
-use core::ops::Deref;
+use core::ops::{Deref, DerefMut};
 use core::ptr::{self, NonNull};
-use core::{fmt, slice};
 
 use hashbrown::{hash_map::DefaultHashBuilder, HashMap};
 
 use crate::borrow::AtomicBorrow;
 use crate::query::Fetch;
-use crate::{Access, Component, Query};
+use crate::{Access, Component, ComponentRef, Query};
 
 /// A collection of entities having the same component types
 ///
@@ -110,18 +110,13 @@ impl Archetype {
         }
     }
 
-    /// Get the `T` components of these entities, if present
+    /// Borrow all components of a single type from these entities, if present
+    ///
+    /// `T` must be a shared or unique reference to a component type.
     ///
     /// Useful for efficient serialization.
-    pub fn get<T: Component>(&self) -> Option<ArchetypeColumn<'_, T>> {
-        let state = self.get_state::<T>()?;
-        let ptr = self.get_base::<T>(state);
-        let column = unsafe { slice::from_raw_parts_mut(ptr.as_ptr(), self.len as usize) };
-        self.borrow::<T>(state);
-        Some(ArchetypeColumn {
-            archetype: self,
-            column,
-        })
+    pub fn get<'a, T: ComponentRef<'a>>(&'a self) -> Option<T::Column> {
+        T::get_column(self)
     }
 
     pub(crate) fn borrow<T: Component>(&self, state: usize) {
@@ -598,6 +593,16 @@ pub struct ArchetypeColumn<'a, T: Component> {
     column: &'a [T],
 }
 
+impl<'a, T: Component> ArchetypeColumn<'a, T> {
+    pub(crate) fn new(archetype: &'a Archetype) -> Option<Self> {
+        let state = archetype.get_state::<T>()?;
+        let ptr = archetype.get_base::<T>(state);
+        let column = unsafe { core::slice::from_raw_parts(ptr.as_ptr(), archetype.len() as usize) };
+        archetype.borrow::<T>(state);
+        Some(Self { archetype, column })
+    }
+}
+
 impl<T: Component> Deref for ArchetypeColumn<'_, T> {
     type Target = [T];
     fn deref(&self) -> &[T] {
@@ -628,3 +633,46 @@ impl<T: Component + fmt::Debug> fmt::Debug for ArchetypeColumn<'_, T> {
         self.column.fmt(f)
     }
 }
+
+/// Unique reference to a single column of component data in an [`Archetype`]
+pub struct ArchetypeColumnMut<'a, T: Component> {
+    archetype: &'a Archetype,
+    column: &'a mut [T],
+}
+
+impl<'a, T: Component> ArchetypeColumnMut<'a, T> {
+    pub(crate) fn new(archetype: &'a Archetype) -> Option<Self> {
+        let state = archetype.get_state::<T>()?;
+        let ptr = archetype.get_base::<T>(state);
+        let column =
+            unsafe { core::slice::from_raw_parts_mut(ptr.as_ptr(), archetype.len() as usize) };
+        archetype.borrow_mut::<T>(state);
+        Some(Self { archetype, column })
+    }
+}
+
+impl<T: Component> Deref for ArchetypeColumnMut<'_, T> {
+    type Target = [T];
+    fn deref(&self) -> &[T] {
+        self.column
+    }
+}
+
+impl<T: Component> DerefMut for ArchetypeColumnMut<'_, T> {
+    fn deref_mut(&mut self) -> &mut [T] {
+        self.column
+    }
+}
+
+impl<T: Component> Drop for ArchetypeColumnMut<'_, T> {
+    fn drop(&mut self) {
+        let state = self.archetype.get_state::<T>().unwrap();
+        self.archetype.release_mut::<T>(state);
+    }
+}
+
+impl<T: Component + fmt::Debug> fmt::Debug for ArchetypeColumnMut<'_, T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.column.fmt(f)
+    }
+}
diff --git a/src/command_buffer.rs b/src/command_buffer.rs
index d85b7bf..5ab2d75 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::<i32>(entity).unwrap(), 42);
+/// assert_eq!(*world.get::<&i32>(entity).unwrap(), 42);
 /// ```
 pub struct CommandBuffer {
     entities: Vec<EntityIndex>,
diff --git a/src/entity_builder.rs b/src/entity_builder.rs
index 4bf5c05..cd5f09d 100644
--- a/src/entity_builder.rs
+++ b/src/entity_builder.rs
@@ -14,7 +14,7 @@ use core::ptr::{self, NonNull};
 use hashbrown::hash_map::Entry;
 
 use crate::archetype::{TypeIdMap, TypeInfo};
-use crate::{align, Component, DynamicBundle};
+use crate::{align, Component, ComponentRef, ComponentRefShared, DynamicBundle};
 
 /// Helper for incrementally constructing a bundle of components with dynamic component types
 ///
@@ -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::<i32>(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 {
@@ -76,13 +76,17 @@ impl EntityBuilder {
         self.inner.has::<T>()
     }
 
-    /// Borrow the component of type `T`, if it exists
-    pub fn get<T: Component>(&self) -> Option<&T> {
+    /// Borrow a shared reference `T` to some component type, if it exists
+    ///
+    /// Takes a reference as its type parameter for consistency with
+    /// [`EntityRef::get`](crate::EntityRef::get), even though it cannot be a unique reference
+    /// because `EntityBuilder` does not perform dynamic borrow checking.
+    pub fn get<'a, T: ComponentRefShared<'a>>(&'a self) -> Option<T> {
         self.inner.get::<T>()
     }
 
-    /// Uniquely borrow the component of type `T`, if it exists
-    pub fn get_mut<T: Component>(&mut self) -> Option<&mut T> {
+    /// Borrow a shared or unique reference `T` to some component type, if it exists
+    pub fn get_mut<'a, T: ComponentRef<'a>>(&'a mut self) -> Option<T> {
         self.inner.get_mut::<T>()
     }
 
@@ -142,10 +146,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::<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");
+/// 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 {
@@ -197,13 +201,17 @@ impl EntityBuilderClone {
         self.inner.has::<T>()
     }
 
-    /// Borrow the component of type `T`, if it exists
-    pub fn get<T: Component>(&self) -> Option<&T> {
+    /// Borrow a shared reference `T` to some component type, if it exists
+    ///
+    /// Takes a reference as its type parameter for consistency with
+    /// [`EntityRef::get`](crate::EntityRef::get), even though it cannot be a unique reference
+    /// because `EntityBuilderClone` does not perform dynamic borrow checking.
+    pub fn get<'a, T: ComponentRefShared<'a>>(&'a self) -> Option<T> {
         self.inner.get::<T>()
     }
 
-    /// Uniquely borrow the component of type `T`, if it exists
-    pub fn get_mut<T: Component>(&mut self) -> Option<&mut T> {
+    /// Borrow a shared or unique reference `T` to some component type, if it exists
+    pub fn get_mut<'a, T: ComponentRef<'a>>(&'a mut self) -> Option<T> {
         self.inner.get_mut::<T>()
     }
 
@@ -283,21 +291,21 @@ impl<M> Common<M> {
         self.indices.contains_key(&TypeId::of::<T>())
     }
 
-    fn get<T: Component>(&self) -> Option<&T> {
-        let index = self.indices.get(&TypeId::of::<T>())?;
+    fn get<'a, T: ComponentRefShared<'a>>(&'a self) -> Option<T> {
+        let index = self.indices.get(&TypeId::of::<T::Component>())?;
         let (_, offset, _) = self.info[*index];
         unsafe {
-            let storage = self.storage.as_ptr().add(offset).cast::<T>();
-            Some(&*storage)
+            let storage = self.storage.as_ptr().add(offset).cast::<T::Component>();
+            Some(T::from_raw(storage))
         }
     }
 
-    fn get_mut<T: Component>(&mut self) -> Option<&mut T> {
-        let index = self.indices.get(&TypeId::of::<T>())?;
+    fn get_mut<'a, T: ComponentRef<'a>>(&'a self) -> Option<T> {
+        let index = self.indices.get(&TypeId::of::<T::Component>())?;
         let (_, offset, _) = self.info[*index];
         unsafe {
-            let storage = self.storage.as_ptr().add(offset).cast::<T>();
-            Some(&mut *storage)
+            let storage = self.storage.as_ptr().add(offset).cast::<T::Component>();
+            Some(T::from_raw(storage))
         }
     }
 
diff --git a/src/entity_ref.rs b/src/entity_ref.rs
index 1db5326..1e6d892 100644
--- a/src/entity_ref.rs
+++ b/src/entity_ref.rs
@@ -3,7 +3,10 @@ use core::ops::{Deref, DerefMut};
 use core::ptr::NonNull;
 
 use crate::archetype::Archetype;
-use crate::{Component, Entity, MissingComponent, Query, QueryOne};
+use crate::{
+    ArchetypeColumn, ArchetypeColumnMut, Component, Entity, Fetch, MissingComponent, Query,
+    QueryOne,
+};
 
 /// Handle to an entity with any component types
 #[derive(Copy, Clone)]
@@ -28,24 +31,36 @@ impl<'a> EntityRef<'a> {
         self.entity
     }
 
+    /// Determine whether this entity would satisfy the query `Q`
+    pub fn satisfies<Q: Query>(&self) -> bool {
+        Q::Fetch::access(self.archetype).is_some()
+    }
+
     /// Determine whether this entity has a `T` component without borrowing it
+    ///
+    /// Equivalent to [`satisfies::<&T>`](Self::satisfies)
     pub fn has<T: Component>(&self) -> bool {
         self.archetype.has::<T>()
     }
 
-    /// 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<T: Component>(&self) -> Option<Ref<'a, T>> {
-        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<T: Component>(&self) -> Option<RefMut<'a, T>> {
-        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<T: ComponentRef<'a>>(&self) -> Option<T::Ref> {
+        T::get_component(*self)
     }
 
     /// Run a query against this entity
@@ -184,3 +199,85 @@ 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;
+
+    /// Smart pointer to a column of the referenced type in an [`Archetype`](crate::Archetype)
+    #[doc(hidden)]
+    type Column;
+
+    /// Component type referenced by `Ref`
+    #[doc(hidden)]
+    type Component: Component;
+
+    /// Fetch the component from `entity`
+    #[doc(hidden)]
+    fn get_component(entity: EntityRef<'a>) -> Option<Self::Ref>;
+
+    /// Construct from a raw pointer
+    ///
+    /// # Safety
+    ///
+    /// Dereferencing `raw` for lifetime `'a` must be sound
+    #[doc(hidden)]
+    unsafe fn from_raw(raw: *mut Self::Component) -> Self;
+
+    /// Borrow a column from an archetype
+    #[doc(hidden)]
+    fn get_column(archetype: &'a Archetype) -> Option<Self::Column>;
+}
+
+impl<'a, T: Component> ComponentRef<'a> for &'a T {
+    type Ref = Ref<'a, T>;
+
+    type Column = ArchetypeColumn<'a, T>;
+
+    type Component = T;
+
+    fn get_component(entity: EntityRef<'a>) -> Option<Self::Ref> {
+        Some(unsafe { Ref::new(entity.archetype, entity.index).ok()? })
+    }
+
+    unsafe fn from_raw(raw: *mut Self::Component) -> Self {
+        &*raw
+    }
+
+    fn get_column(archetype: &'a Archetype) -> Option<Self::Column> {
+        ArchetypeColumn::new(archetype)
+    }
+}
+
+impl<'a, T: Component> ComponentRef<'a> for &'a mut T {
+    type Ref = RefMut<'a, T>;
+
+    type Column = ArchetypeColumnMut<'a, T>;
+
+    type Component = T;
+
+    fn get_component(entity: EntityRef<'a>) -> Option<Self::Ref> {
+        Some(unsafe { RefMut::new(entity.archetype, entity.index).ok()? })
+    }
+
+    unsafe fn from_raw(raw: *mut Self::Component) -> Self {
+        &mut *raw
+    }
+
+    fn get_column(archetype: &'a Archetype) -> Option<Self::Column> {
+        ArchetypeColumnMut::new(archetype)
+    }
+}
+
+/// `&T` where `T` is some component type
+///
+/// Used when consistency demands that references to component types, rather than component types
+/// themselves, be supplied as a type parameter to a function that cannot operate on unique
+/// references.
+pub trait ComponentRefShared<'a>: ComponentRef<'a> {}
+
+impl<'a, T: Component> ComponentRefShared<'a> for &'a T {}
diff --git a/src/lib.rs b/src/lib.rs
index 95f1db1..2fdc76e 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::<i32>(a).unwrap(), 246);
-//! assert_eq!(*world.get::<i32>(b).unwrap(), 42);
+//! assert_eq!(*world.get::<&i32>(a).unwrap(), 246);
+//! assert_eq!(*world.get::<&i32>(b).unwrap(), 42);
 //! ```
 
 #![warn(missing_docs)]
@@ -72,14 +72,14 @@ pub mod serialize;
 mod take;
 mod world;
 
-pub use archetype::{Archetype, ArchetypeColumn};
+pub use archetype::{Archetype, ArchetypeColumn, ArchetypeColumnMut};
 pub use batch::{BatchIncomplete, BatchWriter, ColumnBatch, ColumnBatchBuilder, ColumnBatchType};
 pub use bundle::{Bundle, DynamicBundle, DynamicBundleClone, MissingComponent};
 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, ComponentRefShared, 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/query.rs b/src/query.rs
index 80e4981..0068eaf 100644
--- a/src/query.rs
+++ b/src/query.rs
@@ -365,7 +365,7 @@ unsafe impl<'a, L: Fetch<'a>, R: Fetch<'a>> Fetch<'a> for FetchOr<L, R> {
     }
 }
 
-/// Query transformer skipping entities that have a `T` component
+/// Query transformer skipping entities that satisfy another query
 ///
 /// See also `QueryBorrow::without`.
 ///
@@ -376,24 +376,24 @@ unsafe impl<'a, L: Fetch<'a>, R: Fetch<'a>> Fetch<'a> for FetchOr<L, R> {
 /// let a = world.spawn((123, true, "abc"));
 /// let b = world.spawn((456, false));
 /// let c = world.spawn((42, "def"));
-/// let entities = world.query::<Without<bool, &i32>>()
+/// let entities = world.query::<Without<&i32, &bool>>()
 ///     .iter()
 ///     .map(|(e, &i)| (e, i))
 ///     .collect::<Vec<_>>();
 /// assert_eq!(entities, &[(c, 42)]);
 /// ```
-pub struct Without<T, Q>(PhantomData<(Q, fn(T))>);
+pub struct Without<Q, R>(PhantomData<(Q, fn(R))>);
 
-impl<T: Component, Q: Query> Query for Without<T, Q> {
-    type Fetch = FetchWithout<T, Q::Fetch>;
+impl<Q: Query, R: Query> Query for Without<Q, R> {
+    type Fetch = FetchWithout<Q::Fetch, R::Fetch>;
 }
 
-unsafe impl<T, Q: QueryShared> QueryShared for Without<T, Q> {}
+unsafe impl<Q: QueryShared, R> QueryShared for Without<Q, R> {}
 
 #[doc(hidden)]
-pub struct FetchWithout<T, F>(F, PhantomData<fn(T)>);
+pub struct FetchWithout<F, G>(F, PhantomData<fn(G)>);
 
-unsafe impl<'a, T: Component, F: Fetch<'a>> Fetch<'a> for FetchWithout<T, F> {
+unsafe impl<'a, F: Fetch<'a>, G: Fetch<'a>> Fetch<'a> for FetchWithout<F, G> {
     type Item = F::Item;
 
     type State = F::State;
@@ -403,7 +403,7 @@ unsafe impl<'a, T: Component, F: Fetch<'a>> Fetch<'a> for FetchWithout<T, F> {
     }
 
     fn access(archetype: &Archetype) -> Option<Access> {
-        if archetype.has::<T>() {
+        if G::access(archetype).is_some() {
             None
         } else {
             F::access(archetype)
@@ -414,7 +414,7 @@ unsafe impl<'a, T: Component, F: Fetch<'a>> Fetch<'a> for FetchWithout<T, F> {
         F::borrow(archetype, state)
     }
     fn prepare(archetype: &Archetype) -> Option<Self::State> {
-        if archetype.has::<T>() {
+        if G::access(archetype).is_some() {
             return None;
         }
         F::prepare(archetype)
@@ -435,7 +435,7 @@ unsafe impl<'a, T: Component, F: Fetch<'a>> Fetch<'a> for FetchWithout<T, F> {
     }
 }
 
-/// Query transformer skipping entities that do not have a `T` component
+/// Query transformer skipping entities that do not satisfy another query
 ///
 /// See also `QueryBorrow::with`.
 ///
@@ -446,7 +446,7 @@ unsafe impl<'a, T: Component, F: Fetch<'a>> Fetch<'a> for FetchWithout<T, F> {
 /// let a = world.spawn((123, true, "abc"));
 /// let b = world.spawn((456, false));
 /// let c = world.spawn((42, "def"));
-/// let entities = world.query::<With<bool, &i32>>()
+/// let entities = world.query::<With<&i32, &bool>>()
 ///     .iter()
 ///     .map(|(e, &i)| (e, i))
 ///     .collect::<Vec<_>>();
@@ -454,18 +454,18 @@ unsafe impl<'a, T: Component, F: Fetch<'a>> Fetch<'a> for FetchWithout<T, F> {
 /// assert!(entities.contains(&(a, 123)));
 /// assert!(entities.contains(&(b, 456)));
 /// ```
-pub struct With<T, Q>(PhantomData<(Q, fn(T))>);
+pub struct With<Q, R>(PhantomData<(Q, fn(R))>);
 
-impl<T: Component, Q: Query> Query for With<T, Q> {
-    type Fetch = FetchWith<T, Q::Fetch>;
+impl<Q: Query, R: Query> Query for With<Q, R> {
+    type Fetch = FetchWith<Q::Fetch, R::Fetch>;
 }
 
-unsafe impl<T, Q: QueryShared> QueryShared for With<T, Q> {}
+unsafe impl<Q: QueryShared, R> QueryShared for With<Q, R> {}
 
 #[doc(hidden)]
-pub struct FetchWith<T, F>(F, PhantomData<fn(T)>);
+pub struct FetchWith<F, G>(F, PhantomData<fn(G)>);
 
-unsafe impl<'a, T: Component, F: Fetch<'a>> Fetch<'a> for FetchWith<T, F> {
+unsafe impl<'a, F: Fetch<'a>, G: Fetch<'a>> Fetch<'a> for FetchWith<F, G> {
     type Item = F::Item;
 
     type State = F::State;
@@ -475,7 +475,7 @@ unsafe impl<'a, T: Component, F: Fetch<'a>> Fetch<'a> for FetchWith<T, F> {
     }
 
     fn access(archetype: &Archetype) -> Option<Access> {
-        if archetype.has::<T>() {
+        if G::access(archetype).is_some() {
             F::access(archetype)
         } else {
             None
@@ -486,9 +486,7 @@ unsafe impl<'a, T: Component, F: Fetch<'a>> Fetch<'a> for FetchWith<T, F> {
         F::borrow(archetype, state)
     }
     fn prepare(archetype: &Archetype) -> Option<Self::State> {
-        if !archetype.has::<T>() {
-            return None;
-        }
+        G::access(archetype)?;
         F::prepare(archetype)
     }
     fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
@@ -622,10 +620,9 @@ impl<'w, Q: Query> QueryBorrow<'w, Q> {
         self.borrowed = true;
     }
 
-    /// Transform the query into one that requires a certain component without borrowing it
+    /// Transform the query into one that requires another query be satisfied
     ///
-    /// This can be useful when the component needs to be borrowed elsewhere and it isn't necessary
-    /// for the iterator to expose its data directly.
+    /// Convenient when the values of the components in the other query are not of interest.
     ///
     /// Equivalent to using a query type wrapped in `With`.
     ///
@@ -637,18 +634,19 @@ impl<'w, Q: Query> QueryBorrow<'w, Q> {
     /// let b = world.spawn((456, false));
     /// let c = world.spawn((42, "def"));
     /// let entities = world.query::<&i32>()
-    ///     .with::<bool>()
+    ///     .with::<&bool>()
     ///     .iter()
     ///     .map(|(e, &i)| (e, i)) // Copy out of the world
     ///     .collect::<Vec<_>>();
+    /// assert_eq!(entities.len(), 2);
     /// assert!(entities.contains(&(a, 123)));
     /// assert!(entities.contains(&(b, 456)));
     /// ```
-    pub fn with<T: Component>(self) -> QueryBorrow<'w, With<T, Q>> {
+    pub fn with<R: Query>(self) -> QueryBorrow<'w, With<Q, R>> {
         self.transform()
     }
 
-    /// Transform the query into one that skips entities having a certain component
+    /// Transform the query into one that skips entities satisfying another
     ///
     /// Equivalent to using a query type wrapped in `Without`.
     ///
@@ -660,13 +658,13 @@ impl<'w, Q: Query> QueryBorrow<'w, Q> {
     /// let b = world.spawn((456, false));
     /// let c = world.spawn((42, "def"));
     /// let entities = world.query::<&i32>()
-    ///     .without::<bool>()
+    ///     .without::<&bool>()
     ///     .iter()
     ///     .map(|(e, &i)| (e, i)) // Copy out of the world
     ///     .collect::<Vec<_>>();
     /// assert_eq!(entities, &[(c, 42)]);
     /// ```
-    pub fn without<T: Component>(self) -> QueryBorrow<'w, Without<T, Q>> {
+    pub fn without<R: Query>(self) -> QueryBorrow<'w, Without<Q, R>> {
         self.transform()
     }
 
@@ -800,17 +798,17 @@ impl<'q, Q: Query> QueryMut<'q, Q> {
         unsafe { View::new(self.iter.meta, self.iter.archetypes.as_slice()) }
     }
 
-    /// Transform the query into one that requires a certain component without borrowing it
+    /// Transform the query into one that requires another query be satisfied
     ///
     /// See `QueryBorrow::with`
-    pub fn with<T: Component>(self) -> QueryMut<'q, With<T, Q>> {
+    pub fn with<R: Query>(self) -> QueryMut<'q, With<Q, R>> {
         self.transform()
     }
 
-    /// Transform the query into one that skips entities having a certain component
+    /// Transform the query into one that skips entities satisfying another
     ///
     /// See `QueryBorrow::without`
-    pub fn without<T: Component>(self) -> QueryMut<'q, Without<T, Q>> {
+    pub fn without<R: Query>(self) -> QueryMut<'q, Without<Q, R>> {
         self.transform()
     }
 
diff --git a/src/query_one.rs b/src/query_one.rs
index 3e0245f..d791c2e 100644
--- a/src/query_one.rs
+++ b/src/query_one.rs
@@ -1,7 +1,7 @@
 use core::marker::PhantomData;
 
 use crate::query::{Fetch, With, Without};
-use crate::{Archetype, Component, Query, QueryItem};
+use crate::{Archetype, Query, QueryItem};
 
 /// A borrow of a [`World`](crate::World) sufficient to execute the query `Q` on a single entity
 pub struct QueryOne<'a, Q: Query> {
@@ -44,17 +44,17 @@ impl<'a, Q: Query> QueryOne<'a, Q> {
         unsafe { Some(fetch.get(self.index as usize)) }
     }
 
-    /// Transform the query into one that requires a certain component without borrowing it
+    /// Transform the query into one that requires another query be satisfied
     ///
-    /// See `QueryBorrow::with` for details.
-    pub fn with<T: Component>(self) -> QueryOne<'a, With<T, Q>> {
+    /// See `QueryBorrow::with`
+    pub fn with<R: Query>(self) -> QueryOne<'a, With<Q, R>> {
         self.transform()
     }
 
-    /// Transform the query into one that skips entities having a certain component
+    /// Transform the query into one that skips entities satisfying another
     ///
     /// See `QueryBorrow::without` for details.
-    pub fn without<T: Component>(self) -> QueryOne<'a, Without<T, Q>> {
+    pub fn without<R: Query>(self) -> QueryOne<'a, Without<Q, R>> {
         self.transform()
     }
 
diff --git a/src/serialize/column.rs b/src/serialize/column.rs
index 1b1d3bb..d35197e 100644
--- a/src/serialize/column.rs
+++ b/src/serialize/column.rs
@@ -130,7 +130,7 @@ where
     T: Component + Serialize,
     S: SerializeTuple,
 {
-    if let Some(xs) = archetype.get::<T>() {
+    if let Some(xs) = archetype.get::<&T>() {
         serialize_collection(&*xs, out)?;
     }
     Ok(())
@@ -757,7 +757,7 @@ mod tests {
     impl PartialEq for SerWorld {
         fn eq(&self, other: &Self) -> bool {
             fn same_components<T: Component + PartialEq>(x: &EntityRef, y: &EntityRef) -> bool {
-                x.get::<T>().as_ref().map(|x| &**x) == y.get::<T>().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::<Position>().map(|x| *x),
-                            e.get::<Velocity>().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 cbbebeb..6495d29 100644
--- a/src/serialize/row.rs
+++ b/src/serialize/row.rs
@@ -82,7 +82,7 @@ pub fn try_serialize<T: Component + Serialize, K: Serialize + ?Sized, S: Seriali
     key: &K,
     map: &mut S,
 ) -> Result<(), S::Error> {
-    if let Some(x) = entity.get::<T>() {
+    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<T: Component + PartialEq>(x: &EntityRef, y: &EntityRef) -> bool {
-                x.get::<T>().as_ref().map(|x| &**x) == y.get::<T>().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::<Position>().map(|x| *x),
-                            e.get::<Velocity>().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 878503a..8caec15 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::<Vec<_>>();
     /// for i in 0..1_000 {
-    ///     assert_eq!(*world.get::<i32>(entities[i]).unwrap(), i as i32);
+    ///     assert_eq!(*world.get::<&i32>(entities[i]).unwrap(), i as i32);
     /// }
     /// ```
     pub fn spawn_batch<I>(&mut self, iter: I) -> SpawnBatchIter<'_, I::IntoIter>
@@ -469,25 +468,20 @@ 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<T: Component>(&self, entity: Entity) -> Result<Ref<'_, T>, ComponentError> {
+    /// Short-hand for [`entity`](Self::entity) followed by [`EntityRef::get`]
+    pub fn get<'a, T: ComponentRef<'a>>(
+        &'a self,
+        entity: Entity,
+    ) -> Result<T::Ref, ComponentError> {
         Ok(self
             .entity(entity)?
-            .get()
-            .ok_or_else(MissingComponent::new::<T>)?)
+            .get::<T>()
+            .ok_or_else(MissingComponent::new::<T::Component>)?)
     }
 
-    /// 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<T: Component>(&self, entity: Entity) -> Result<RefMut<'_, T>, ComponentError> {
-        Ok(self
-            .entity(entity)?
-            .get_mut()
-            .ok_or_else(MissingComponent::new::<T>)?)
+    /// Short-hand for [`entity`](Self::entity) followed by [`EntityRef::satisfies`]
+    pub fn satisfies<Q: Query>(&self, entity: Entity) -> Result<bool, NoSuchEntity> {
+        Ok(self.entity(entity)?.satisfies::<Q>())
     }
 
     /// Access an entity regardless of its component types
@@ -547,8 +541,8 @@ impl World {
     /// let mut world = World::new();
     /// let e = world.spawn((123, "abc"));
     /// world.insert(e, (456, true));
-    /// assert_eq!(*world.get::<i32>(e).unwrap(), 456);
-    /// assert_eq!(*world.get::<bool>(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 +660,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::<i32>(e).is_err());
-    /// assert!(world.get::<&str>(e).is_err());
-    /// assert_eq!(*world.get::<bool>(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<T: Bundle + 'static>(&mut self, entity: Entity) -> Result<T, ComponentError> {
         self.flush();
@@ -1389,13 +1383,13 @@ mod tests {
     fn reuse_populated() {
         let mut world = World::new();
         let a = world.spawn((42,));
-        assert_eq!(*world.get::<i32>(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::<i32>(b).is_err());
-        assert!(*world.get::<bool>(b).unwrap());
+        assert!(world.get::<&i32>(b).is_err());
+        assert!(*world.get::<&bool>(b).unwrap());
     }
 
     #[test]


Test patch:
diff --git a/tests/tests.rs b/tests/tests.rs
index 44354c9..44ac367 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::<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);
+    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::<i32>(e).is_err());
-    assert_eq!(*world.get::<&str>(f).unwrap(), "def");
-    assert_eq!(*world.get::<i32>(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::<i32>(e).unwrap(), 123);
-    assert_eq!(*world.get::<&str>(f).unwrap(), "def");
-    assert_eq!(*world.get::<i32>(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::<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::<&&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::<Cow<'static, str>>(g).unwrap(), "after");
+    assert_eq!(*world.get::<&Cow<'static, str>>(g).unwrap(), "after");
 }
 
 #[test]
@@ -326,8 +326,8 @@ fn build_builder_clone() {
     let mut b = EntityBuilderClone::new();
     b.add(String::from("def"));
     b.add_bundle(&a.build());
-    assert_eq!(b.get::<String>(), Some(&String::from("abc")));
-    assert_eq!(b.get::<i32>(), Some(&123));
+    assert_eq!(b.get::<&String>(), Some(&String::from("abc")));
+    assert_eq!(b.get::<&i32>(), Some(&123));
 }
 
 #[test]
@@ -337,8 +337,8 @@ fn cloned_builder() {
 
     let mut world = World::new();
     let e = world.spawn(&builder.build().clone());
-    assert_eq!(*world.get::<String>(e).unwrap(), "abc");
-    assert_eq!(*world.get::<i32>(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::<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::<&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::<Cow<'static, str>>(g).unwrap(), "after");
+    assert_eq!(*world.get::<&Cow<'static, str>>(g).unwrap(), "after");
 }
 
 #[test]
@@ -386,17 +386,17 @@ fn access_builder_components() {
     assert!(entity.has::<i32>());
     assert!(!entity.has::<usize>());
 
-    assert_eq!(*entity.get::<&str>().unwrap(), "abc");
-    assert_eq!(*entity.get::<i32>().unwrap(), 123);
-    assert_eq!(entity.get::<usize>(), None);
+    assert_eq!(*entity.get::<&&str>().unwrap(), "abc");
+    assert_eq!(*entity.get::<&i32>().unwrap(), 123);
+    assert_eq!(entity.get::<&usize>(), None);
 
-    *entity.get_mut::<i32>().unwrap() = 456;
-    assert_eq!(*entity.get::<i32>().unwrap(), 456);
+    *entity.get_mut::<&mut i32>().unwrap() = 456;
+    assert_eq!(*entity.get::<&i32>().unwrap(), 456);
 
     let g = world.spawn(entity.build());
 
-    assert_eq!(*world.get::<&str>(g).unwrap(), "abc");
-    assert_eq!(*world.get::<i32>(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::<i32>(e).unwrap(), 123);
-    assert_eq!(*world.get::<&str>(f).unwrap(), "def");
-    assert_eq!(*world.get::<i32>(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::<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);
+    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::<i32>(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::<i32>(e).unwrap();
-    world.get::<i32>(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::<i32>(e).unwrap(), 42);
-    assert_eq!(*world.get::<char>(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::<String>(entity).is_ok());
-    assert!(world.get::<i32>(entity).is_ok());
-    assert!(world.get::<bool>(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::<String, _>(entity, true).unwrap();
-    assert!(world.get::<String>(entity).is_err());
-    assert!(world.get::<i32>(entity).is_ok());
-    assert!(world.get::<bool>(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::<Vec<_>>();
         assert_eq!(entities.len(), 2);
-        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);
+        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);
     }
 }
 
@@ -788,11 +788,11 @@ fn columnar_access() {
     let _empty = archetypes.next().unwrap();
     let a = archetypes.next().unwrap();
     assert_eq!(a.ids(), &[e.id()]);
-    assert_eq!(*a.get::<i32>().unwrap(), [123]);
-    assert!(a.get::<bool>().is_none());
+    assert_eq!(*a.get::<&i32>().unwrap(), [123]);
+    assert!(a.get::<&bool>().is_none());
     let b = archetypes.next().unwrap();
     assert_eq!(b.ids(), &[f.id(), g.id()]);
-    assert_eq!(*b.get::<i32>().unwrap(), [456, 789]);
+    assert_eq!(*b.get::<&i32>().unwrap(), [456, 789]);
 }
 
 #[test]
@@ -840,7 +840,7 @@ fn column_get_mut() {
         *column.get(ent).unwrap() = 99;
         assert_eq!(*column.get(ent).unwrap(), 99);
     }
-    assert_eq!(*world.get::<i32>(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::<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);
+    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));
 }