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

View File

@ -11,6 +11,7 @@ use crate::{
},
world::unsafe_world_cell::UnsafeWorldCell,
};
use alloc::boxed::Box;
use core::{
marker::PhantomData,
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)));
/// #
/// 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.
@ -1846,7 +1847,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: Deref<Target = QueryState<D, F>>>
/// # world.spawn((A(10), B(5)));
/// #
/// 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.
@ -1909,12 +1910,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: Deref<Target = QueryState<D, F>>>
self,
) -> QueryLens<'w, NewD, NewF> {
let state = self.state.transmute_filtered::<NewD, NewF>(self.world);
QueryLens {
world: self.world,
state,
last_run: self.last_run,
this_run: self.this_run,
}
// SAFETY:
// - This is memory safe because the original query had compatible access and was consumed.
// - The world matches because it was the same one used to construct self.
unsafe { Query::new(self.world, Box::new(state), self.last_run, self.this_run) }
}
/// 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>
/// ) {
/// 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
/// }
///
/// 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
/// }
/// }
@ -2063,12 +2062,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: Deref<Target = QueryState<D, F>>>
let state = self
.state
.join_filtered::<OtherD, OtherF, NewD, NewF>(self.world, other.state);
QueryLens {
world: self.world,
state,
last_run: self.last_run,
this_run: self.this_run,
}
// SAFETY:
// - This is memory safe because the original query had compatible access and was consumed.
// - The world matches because it was the same one used to construct self.
unsafe { Query::new(self.world, Box::new(state), self.last_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`]
pub struct QueryLens<'w, Q: QueryData, F: QueryFilter = ()> {
world: UnsafeWorldCell<'w>,
state: QueryState<Q, F>,
last_run: Tick,
this_run: Tick,
}
/// This is returned from methods like [`Query::transmute_lens`] that construct a fresh [`QueryState`].
pub type QueryLens<'w, Q, F = ()> = Query<'w, 'static, Q, F, Box<QueryState<Q, F>>>;
impl<'w, Q: QueryData, F: QueryFilter> QueryLens<'w, Q, F> {
/// 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> {
Query {
world: self.world,
state: &self.state,
last_run: self.last_run,
this_run: self.this_run,
marker: PhantomData,
}
self.reborrow()
}
}
@ -2587,7 +2577,7 @@ impl<'w, 's, Q: QueryData, F: QueryFilter> From<&'s mut QueryLens<'w, Q, F>>
for 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());
}
```