Repository: Ralith/hecs
Pull request #228 (2021-12-26 23:59:26)

View::get_unchecked


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index eaa4e9f..e68767c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+# Unreleased
+
+### Added
+- `get_unchecked` methods on `View` and `PreparedView` for overlapping borrows
+
 # 0.7.2
 
 ### Added
diff --git a/Cargo.toml b/Cargo.toml
index 5210c18..5be644a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "hecs"
-version = "0.7.2"
+version = "0.7.3"
 description = "A fast, minimal, and ergonomic entity-component-system library"
 authors = ["Benjamin Saunders <ben.e.saunders@gmail.com>"]
 edition = "2018"
@@ -28,7 +28,7 @@ column-serialize = ["serde"]
 row-serialize = ["serde"]
 
 [dependencies]
-hecs-macros = { path = "macros", version = "0.7.0", optional = true }
+hecs-macros = { path = "macros", version = "0.7.1", optional = true }
 hashbrown = { version = "0.11.0", default-features = false, features = ["ahash", "inline-more"] }
 lazy_static = { version = "1.4.0", optional = true, features = ["spin_no_std"] }
 serde = { version = "1.0.117", default-features = false, optional = true }
diff --git a/macros/Cargo.toml b/macros/Cargo.toml
index 40bcaf9..77c231a 100644
--- a/macros/Cargo.toml
+++ b/macros/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "hecs-macros"
-version = "0.7.0"
+version = "0.7.1"
 description = "Procedural macro definitions for hecs"
 authors = ["Benjamin Saunders <ben.e.saunders@gmail.com>"]
 edition = "2018"
diff --git a/src/column.rs b/src/column.rs
index 9e7c793..855c53b 100644
--- a/src/column.rs
+++ b/src/column.rs
@@ -143,6 +143,7 @@ impl<'a, T: Component> Drop for ColumnMut<'a, T> {
 }
 
 #[cfg(test)]
+#[allow(deprecated)]
 mod tests {
     use crate::World;
 
diff --git a/src/lib.rs b/src/lib.rs
index 60e3c2f..624dd25 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -101,7 +101,7 @@ pub use lazy_static;
 pub use query::Fetch;
 
 #[cfg(feature = "macros")]
-pub use hecs_macros::{Bundle, Query};
+pub use hecs_macros::{Bundle, DynamicBundleClone, Query};
 
 fn align(x: usize, alignment: usize) -> usize {
     debug_assert!(alignment.is_power_of_two());
diff --git a/src/query.rs b/src/query.rs
index b82658e..fafa602 100644
--- a/src/query.rs
+++ b/src/query.rs
@@ -1306,6 +1306,15 @@ impl<'q, Q: Query> View<'q, Q> {
     ///
     /// Will yield `None` if the entity does not exist or does not match the query.
     pub fn get_mut<'m>(&'m mut self, entity: Entity) -> Option<QueryItem<'q, Q>> {
+        unsafe { self.get_unchecked(entity) }
+    }
+
+    /// Like `get_mut`, but allows simultaneous access to multiple entities
+    ///
+    /// # Safety
+    ///
+    /// Must not be invoked while any unique borrow of the fetched components of `entity` is live.
+    pub unsafe fn get_unchecked(&self, entity: Entity) -> Option<QueryItem<'q, Q>> {
         let meta = self.meta.get(entity.id as usize)?;
         if meta.generation != entity.generation {
             return None;
@@ -1313,7 +1322,7 @@ impl<'q, Q: Query> View<'q, Q> {
 
         self.fetch[meta.location.archetype as usize]
             .as_ref()
-            .map(|fetch| unsafe { fetch.get(meta.location.index as usize) })
+            .map(|fetch| fetch.get(meta.location.index as usize))
     }
 }
 
@@ -1367,6 +1376,15 @@ impl<'q, Q: Query> PreparedView<'q, Q> {
     ///
     /// Will yield `None` if the entity does not exist or does not match the query.
     pub fn get_mut<'m>(&'m mut self, entity: Entity) -> Option<QueryItem<'q, Q>> {
+        unsafe { self.get_unchecked(entity) }
+    }
+
+    /// Like `get_mut`, but allows simultaneous access to multiple entities
+    ///
+    /// # Safety
+    ///
+    /// Must not be invoked while any unique borrow of the fetched components of `entity` is live.
+    pub unsafe fn get_unchecked(&self, entity: Entity) -> Option<QueryItem<'q, Q>> {
         let meta = self.meta.get(entity.id as usize)?;
         if meta.generation != entity.generation {
             return None;
@@ -1374,7 +1392,7 @@ impl<'q, Q: Query> PreparedView<'q, Q> {
 
         self.fetch[meta.location.archetype as usize]
             .as_ref()
-            .map(|fetch| unsafe { fetch.get(meta.location.index as usize) })
+            .map(|fetch| fetch.get(meta.location.index as usize))
     }
 }
 


Test patch:
diff --git a/tests/tests.rs b/tests/tests.rs
index 7fa7232..b4c2194 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -1,3 +1,4 @@
+#![allow(deprecated)]
 // Copyright 2019 Google LLC
 //
 // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or