Make QueryLens a type alias.

This commit is contained in:
Chris Russell 2025-06-18 16:40:54 -04:00
parent fa787b2ae4
commit 1f7241ac16
3 changed files with 44 additions and 34 deletions

View File

@ -2020,7 +2020,7 @@ mod tests {
.run_system_once(|query: Query<&mut A>| { .run_system_once(|query: Query<&mut A>| {
let mut readonly = query.as_readonly(); let mut readonly = query.as_readonly();
let mut lens: QueryLens<&mut A> = readonly.transmute_lens(); let mut lens: QueryLens<&mut A> = readonly.transmute_lens();
bad(lens.query(), query.as_readonly()); bad(lens.reborrow(), query.as_readonly());
}) })
.unwrap(); .unwrap();
} }
@ -2146,7 +2146,7 @@ mod tests {
.run_system_once(|query_a: Query<&mut A>, mut query_b: Query<&mut B>| { .run_system_once(|query_a: Query<&mut A>, mut query_b: Query<&mut B>| {
let mut readonly = query_a.as_readonly(); let mut readonly = query_a.as_readonly();
let mut lens: QueryLens<(&mut A, &mut B)> = readonly.join(&mut query_b); let mut lens: QueryLens<(&mut A, &mut B)> = readonly.join(&mut query_b);
bad(lens.query(), query_a.as_readonly()); bad(lens.reborrow(), query_a.as_readonly());
}) })
.unwrap(); .unwrap();
} }

View File

@ -11,6 +11,7 @@ use crate::{
}, },
world::unsafe_world_cell::UnsafeWorldCell, world::unsafe_world_cell::UnsafeWorldCell,
}; };
use alloc::boxed::Box;
use core::{ use core::{
marker::PhantomData, marker::PhantomData,
mem::MaybeUninit, mem::MaybeUninit,
@ -1717,7 +1718,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: Deref<Target = QueryState<D, F>>>
/// # world.spawn((A(10), B(5))); /// # world.spawn((A(10), B(5)));
/// # /// #
/// fn reusable_function(lens: &mut QueryLens<&A>) { /// fn reusable_function(lens: &mut QueryLens<&A>) {
/// assert_eq!(lens.query().single().unwrap().0, 10); /// assert_eq!(lens.single().unwrap().0, 10);
/// } /// }
/// ///
/// // We can use the function in a system that takes the exact query. /// // We can use the function in a system that takes the exact query.
@ -1846,7 +1847,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: Deref<Target = QueryState<D, F>>>
/// # world.spawn((A(10), B(5))); /// # world.spawn((A(10), B(5)));
/// # /// #
/// fn reusable_function(mut lens: QueryLens<&A>) { /// fn reusable_function(mut lens: QueryLens<&A>) {
/// assert_eq!(lens.query().single().unwrap().0, 10); /// assert_eq!(lens.single().unwrap().0, 10);
/// } /// }
/// ///
/// // We can use the function in a system that takes the exact query. /// // We can use the function in a system that takes the exact query.
@ -1909,12 +1910,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: Deref<Target = QueryState<D, F>>>
self, self,
) -> QueryLens<'w, NewD, NewF> { ) -> QueryLens<'w, NewD, NewF> {
let state = self.state.transmute_filtered::<NewD, NewF>(self.world); let state = self.state.transmute_filtered::<NewD, NewF>(self.world);
QueryLens { // SAFETY:
world: self.world, // - This is memory safe because the original query had compatible access and was consumed.
state, // - The world matches because it was the same one used to construct self.
last_run: self.last_run, unsafe { Query::new(self.world, Box::new(state), self.last_run, self.this_run) }
this_run: self.this_run,
}
} }
/// Gets a [`QueryLens`] with the same accesses as the existing query /// Gets a [`QueryLens`] with the same accesses as the existing query
@ -1963,12 +1962,12 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: Deref<Target = QueryState<D, F>>>
/// mut enemies: Query<&Enemy> /// mut enemies: Query<&Enemy>
/// ) { /// ) {
/// let mut players_transforms: QueryLens<(&Transform, &Player)> = transforms.join(&mut players); /// let mut players_transforms: QueryLens<(&Transform, &Player)> = transforms.join(&mut players);
/// for (transform, player) in &players_transforms.query() { /// for (transform, player) in &players_transforms {
/// // do something with a and b /// // do something with a and b
/// } /// }
/// ///
/// let mut enemies_transforms: QueryLens<(&Transform, &Enemy)> = transforms.join(&mut enemies); /// let mut enemies_transforms: QueryLens<(&Transform, &Enemy)> = transforms.join(&mut enemies);
/// for (transform, enemy) in &enemies_transforms.query() { /// for (transform, enemy) in &enemies_transforms {
/// // do something with a and b /// // do something with a and b
/// } /// }
/// } /// }
@ -2063,12 +2062,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: Deref<Target = QueryState<D, F>>>
let state = self let state = self
.state .state
.join_filtered::<OtherD, OtherF, NewD, NewF>(self.world, other.state); .join_filtered::<OtherD, OtherF, NewD, NewF>(self.world, other.state);
QueryLens { // SAFETY:
world: self.world, // - This is memory safe because the original query had compatible access and was consumed.
state, // - The world matches because it was the same one used to construct self.
last_run: self.last_run, unsafe { Query::new(self.world, Box::new(state), self.last_run, self.this_run) }
this_run: self.this_run,
}
} }
} }
@ -2545,26 +2542,19 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter> Query<'w, 's, D, F> {
} }
} }
/// Type returned from [`Query::transmute_lens`] containing the new [`QueryState`]. /// A [`Query`] with an owned [`QueryState`].
/// ///
/// Call [`query`](QueryLens::query) or [`into`](Into::into) to construct the resulting [`Query`] /// This is returned from methods like [`Query::transmute_lens`] that construct a fresh [`QueryState`].
pub struct QueryLens<'w, Q: QueryData, F: QueryFilter = ()> { pub type QueryLens<'w, Q, F = ()> = Query<'w, 'static, Q, F, Box<QueryState<Q, F>>>;
world: UnsafeWorldCell<'w>,
state: QueryState<Q, F>,
last_run: Tick,
this_run: Tick,
}
impl<'w, Q: QueryData, F: QueryFilter> QueryLens<'w, Q, F> { impl<'w, Q: QueryData, F: QueryFilter> QueryLens<'w, Q, F> {
/// Create a [`Query`] from the underlying [`QueryState`]. /// Create a [`Query`] from the underlying [`QueryState`].
#[deprecated(
since = "0.17.0",
note = "This can usually be removed, since `QueryLens` supports all methods from `Query`. If you need to consume the resulting `Query`, call `reborrow()` instead."
)]
pub fn query(&mut self) -> Query<'_, '_, Q, F> { pub fn query(&mut self) -> Query<'_, '_, Q, F> {
Query { self.reborrow()
world: self.world,
state: &self.state,
last_run: self.last_run,
this_run: self.this_run,
marker: PhantomData,
}
} }
} }
@ -2587,7 +2577,7 @@ impl<'w, 's, Q: QueryData, F: QueryFilter> From<&'s mut QueryLens<'w, Q, F>>
for Query<'s, 's, Q, F> for Query<'s, 's, Q, F>
{ {
fn from(value: &'s mut QueryLens<'w, Q, F>) -> Query<'s, 's, Q, F> { fn from(value: &'s mut QueryLens<'w, Q, F>) -> Query<'s, 's, Q, F> {
value.query() value.reborrow()
} }
} }

View File

@ -0,0 +1,20 @@
---
title: Combine `Query` and `QueryLens`
pull_requests: [18162]
---
The `QueryLens::query()` method has been deprecated.
The `QueryLens` type has now been combined with `Query`, so most methods can be called directly on the `QueryLens` and the call can simply be removed.
If that doesn't work and you do need a fresh `Query`, the call to `.query()` can be replaced with `.reborrow()`.
```rust
fn with_query(query: Query<&T>) {}
fn with_lens(lens: QueryLens<&T>) -> Result {
// 0.16
for item in lens.query().iter() {}
with_query(lens.query());
// 0.17
for item in lens.iter() {}
with_query(lens.reborrow());
}
```