diff --git a/crates/bevy_ecs/src/system/mod.rs b/crates/bevy_ecs/src/system/mod.rs index aef76c277a5ec..7e6fc91ccdb84 100644 --- a/crates/bevy_ecs/src/system/mod.rs +++ b/crates/bevy_ecs/src/system/mod.rs @@ -956,130 +956,6 @@ mod tests { ); } } - - #[test] - fn convert_mut_to_immut() { - { - let mut world = World::new(); - - fn mutable_query(mut query: Query<&mut A>) { - for _ in &mut query {} - - immutable_query(query.to_readonly()); - } - - fn immutable_query(_: Query<&A>) {} - - let mut sys = IntoSystem::into_system(mutable_query); - sys.initialize(&mut world); - } - - { - let mut world = World::new(); - - fn mutable_query(mut query: Query>) { - for _ in &mut query {} - - immutable_query(query.to_readonly()); - } - - fn immutable_query(_: Query>) {} - - let mut sys = IntoSystem::into_system(mutable_query); - sys.initialize(&mut world); - } - - { - let mut world = World::new(); - - fn mutable_query(mut query: Query<(&mut A, &B)>) { - for _ in &mut query {} - - immutable_query(query.to_readonly()); - } - - fn immutable_query(_: Query<(&A, &B)>) {} - - let mut sys = IntoSystem::into_system(mutable_query); - sys.initialize(&mut world); - } - - { - let mut world = World::new(); - - fn mutable_query(mut query: Query<(&mut A, &mut B)>) { - for _ in &mut query {} - - immutable_query(query.to_readonly()); - } - - fn immutable_query(_: Query<(&A, &B)>) {} - - let mut sys = IntoSystem::into_system(mutable_query); - sys.initialize(&mut world); - } - - { - let mut world = World::new(); - - fn mutable_query(mut query: Query<(&mut A, &mut B), With>) { - for _ in &mut query {} - - immutable_query(query.to_readonly()); - } - - fn immutable_query(_: Query<(&A, &B), With>) {} - - let mut sys = IntoSystem::into_system(mutable_query); - sys.initialize(&mut world); - } - - { - let mut world = World::new(); - - fn mutable_query(mut query: Query<(&mut A, &mut B), Without>) { - for _ in &mut query {} - - immutable_query(query.to_readonly()); - } - - fn immutable_query(_: Query<(&A, &B), Without>) {} - - let mut sys = IntoSystem::into_system(mutable_query); - sys.initialize(&mut world); - } - - { - let mut world = World::new(); - - fn mutable_query(mut query: Query<(&mut A, &mut B), Added>) { - for _ in &mut query {} - - immutable_query(query.to_readonly()); - } - - fn immutable_query(_: Query<(&A, &B), Added>) {} - - let mut sys = IntoSystem::into_system(mutable_query); - sys.initialize(&mut world); - } - - { - let mut world = World::new(); - - fn mutable_query(mut query: Query<(&mut A, &mut B), Changed>) { - for _ in &mut query {} - - immutable_query(query.to_readonly()); - } - - fn immutable_query(_: Query<(&A, &B), Changed>) {} - - let mut sys = IntoSystem::into_system(mutable_query); - sys.initialize(&mut world); - } - } - #[test] fn update_archetype_component_access_works() { use std::collections::HashSet; diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 3e4d37914b622..df1e68b457f38 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -302,24 +302,6 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { } } - /// Returns another `Query` from this that fetches the read-only version of the query items. - /// - /// For example, `Query<(&mut A, &B, &mut C), With>` will become `Query<(&A, &B, &C), With>`. - /// This can be useful when working around the borrow checker, - /// or reusing functionality between systems via functions that accept query types. - pub fn to_readonly(&self) -> Query<'_, 's, Q::ReadOnly, F::ReadOnly> { - let new_state = self.state.as_readonly(); - // SAFETY: This is memory safe because it turns the query immutable. - unsafe { - Query::new( - self.world, - new_state, - self.last_change_tick, - self.change_tick, - ) - } - } - /// Returns an [`Iterator`] over the read-only query items. /// /// # Example diff --git a/crates/bevy_ecs_compile_fail_tests/tests/ui/query_to_readonly.rs b/crates/bevy_ecs_compile_fail_tests/tests/ui/query_to_readonly.rs deleted file mode 100644 index 060793023339b..0000000000000 --- a/crates/bevy_ecs_compile_fail_tests/tests/ui/query_to_readonly.rs +++ /dev/null @@ -1,75 +0,0 @@ -use bevy_ecs::prelude::*; - -#[derive(Component, Debug)] -struct Foo; - -fn for_loops(mut query: Query<&mut Foo>) { - // this should fail to compile - for _ in query.iter_mut() { - for _ in query.to_readonly().iter() {} - } - - // this should fail to compile - for _ in query.to_readonly().iter() { - for _ in query.iter_mut() {} - } - - // this should *not* fail to compile - for _ in query.to_readonly().iter() { - for _ in query.to_readonly().iter() {} - } - - // this should *not* fail to compile - for _ in query.to_readonly().iter() { - for _ in query.iter() {} - } - - // this should *not* fail to compile - for _ in query.iter() { - for _ in query.to_readonly().iter() {} - } -} - -fn single_mut_query(mut query: Query<&mut Foo>) { - // this should fail to compile - { - let mut mut_foo = query.single_mut(); - - // This solves "temporary value dropped while borrowed" - let readonly_query = query.to_readonly(); - - let ref_foo = readonly_query.single(); - - *mut_foo = Foo; - - println!("{ref_foo:?}"); - } - - // this should fail to compile - { - // This solves "temporary value dropped while borrowed" - let readonly_query = query.to_readonly(); - - let ref_foo = readonly_query.single(); - - let mut mut_foo = query.single_mut(); - - println!("{ref_foo:?}"); - - *mut_foo = Foo; - } - - // this should *not* fail to compile - { - // This solves "temporary value dropped while borrowed" - let readonly_query = query.to_readonly(); - - let readonly_foo = readonly_query.single(); - - let query_foo = query.single(); - - println!("{readonly_foo:?}, {query_foo:?}"); - } -} - -fn main() {} \ No newline at end of file diff --git a/crates/bevy_ecs_compile_fail_tests/tests/ui/query_to_readonly.stderr b/crates/bevy_ecs_compile_fail_tests/tests/ui/query_to_readonly.stderr deleted file mode 100644 index b57108182203f..0000000000000 --- a/crates/bevy_ecs_compile_fail_tests/tests/ui/query_to_readonly.stderr +++ /dev/null @@ -1,45 +0,0 @@ -error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable - --> tests/ui/query_to_readonly.rs:9:18 - | -8 | for _ in query.iter_mut() { - | ---------------- - | | - | mutable borrow occurs here - | mutable borrow later used here -9 | for _ in query.to_readonly().iter() {} - | ^^^^^^^^^^^^^^^^^^^ immutable borrow occurs here - -error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable - --> tests/ui/query_to_readonly.rs:14:18 - | -13 | for _ in query.to_readonly().iter() { - | -------------------------- - | | - | immutable borrow occurs here - | immutable borrow later used here -14 | for _ in query.iter_mut() {} - | ^^^^^^^^^^^^^^^^ mutable borrow occurs here - -error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable - --> tests/ui/query_to_readonly.rs:39:30 - | -36 | let mut mut_foo = query.single_mut(); - | ------------------ mutable borrow occurs here -... -39 | let readonly_query = query.to_readonly(); - | ^^^^^^^^^^^^^^^^^^^ immutable borrow occurs here -... -43 | *mut_foo = Foo; - | ------- mutable borrow later used here - -error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable - --> tests/ui/query_to_readonly.rs:55:27 - | -51 | let readonly_query = query.to_readonly(); - | ------------------- immutable borrow occurs here -... -55 | let mut mut_foo = query.single_mut(); - | ^^^^^^^^^^^^^^^^^^ mutable borrow occurs here -56 | -57 | println!("{ref_foo:?}"); - | ------- immutable borrow later used here