Skip to content

Commit d0550f5

Browse files
chescockalice-i-cecileecoskey
authored
Remove 's lifetime from WorldQuery::Fetch (#19720)
# Objective Unblock #18162. #15396 added the `'s` lifetime to `QueryData::Item` to make it possible for query items to borrow from the state. The state isn't passed directly to `QueryData::fetch()`, so it also added the `'s` lifetime to `WorldQuery::Fetch` so that we can pass the borrows through there. Unfortunately, having `WorldQuery::Fetch` borrow from the state makes it impossible to have owned state, because we store the state and the `Fetch` in the same `struct` during iteration. ## Solution Undo the change to add the `'s` lifetime to `WorldQuery::Fetch`. Instead, add a `&'s Self::State` parameter to `QueryData::fetch()` and `QueryFilter::filter_fetch()` so that borrows from the state can be passed directly to query items. --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: Emerson Coskey <emerson@coskey.dev>
1 parent 4e694ae commit d0550f5

File tree

13 files changed

+388
-336
lines changed

13 files changed

+388
-336
lines changed

crates/bevy_asset/src/asset_changed.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,11 @@ pub struct AssetChangedState<A: AsAssetId> {
150150
#[expect(unsafe_code, reason = "WorldQuery is an unsafe trait.")]
151151
/// SAFETY: `ROQueryFetch<Self>` is the same as `QueryFetch<Self>`
152152
unsafe impl<A: AsAssetId> WorldQuery for AssetChanged<A> {
153-
type Fetch<'w, 's> = AssetChangedFetch<'w, A>;
153+
type Fetch<'w> = AssetChangedFetch<'w, A>;
154154

155155
type State = AssetChangedState<A>;
156156

157-
fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
158-
fetch: Self::Fetch<'wlong, 's>,
159-
) -> Self::Fetch<'wshort, 's> {
157+
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
160158
fetch
161159
}
162160

@@ -165,7 +163,7 @@ unsafe impl<A: AsAssetId> WorldQuery for AssetChanged<A> {
165163
state: &'s Self::State,
166164
last_run: Tick,
167165
this_run: Tick,
168-
) -> Self::Fetch<'w, 's> {
166+
) -> Self::Fetch<'w> {
169167
// SAFETY:
170168
// - `AssetChanges` is private and only accessed mutably in the `AssetEventSystems` system set.
171169
// - `resource_id` was obtained from the type ID of `AssetChanges<A::Asset>`.
@@ -204,7 +202,7 @@ unsafe impl<A: AsAssetId> WorldQuery for AssetChanged<A> {
204202
const IS_DENSE: bool = <&A>::IS_DENSE;
205203

206204
unsafe fn set_archetype<'w, 's>(
207-
fetch: &mut Self::Fetch<'w, 's>,
205+
fetch: &mut Self::Fetch<'w>,
208206
state: &'s Self::State,
209207
archetype: &'w Archetype,
210208
table: &'w Table,
@@ -218,7 +216,7 @@ unsafe impl<A: AsAssetId> WorldQuery for AssetChanged<A> {
218216
}
219217

220218
unsafe fn set_table<'w, 's>(
221-
fetch: &mut Self::Fetch<'w, 's>,
219+
fetch: &mut Self::Fetch<'w>,
222220
state: &Self::State,
223221
table: &'w Table,
224222
) {
@@ -271,14 +269,15 @@ unsafe impl<A: AsAssetId> QueryFilter for AssetChanged<A> {
271269

272270
#[inline]
273271
unsafe fn filter_fetch(
274-
fetch: &mut Self::Fetch<'_, '_>,
272+
state: &Self::State,
273+
fetch: &mut Self::Fetch<'_>,
275274
entity: Entity,
276275
table_row: TableRow,
277276
) -> bool {
278277
fetch.inner.as_mut().is_some_and(|inner| {
279278
// SAFETY: We delegate to the inner `fetch` for `A`
280279
unsafe {
281-
let handle = <&A>::fetch(inner, entity, table_row);
280+
let handle = <&A>::fetch(&state.asset_id, inner, entity, table_row);
282281
fetch.check.has_changed(handle)
283282
}
284283
})

crates/bevy_ecs/macros/src/query_data.rs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,23 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
7474
let user_generics = ast.generics.clone();
7575
let (user_impl_generics, user_ty_generics, user_where_clauses) = user_generics.split_for_impl();
7676
let user_generics_with_world = {
77-
let mut generics = ast.generics;
77+
let mut generics = ast.generics.clone();
7878
generics.params.insert(0, parse_quote!('__w));
79-
generics.params.insert(0, parse_quote!('__s));
8079
generics
8180
};
8281
let (user_impl_generics_with_world, user_ty_generics_with_world, user_where_clauses_with_world) =
8382
user_generics_with_world.split_for_impl();
83+
let user_generics_with_world_and_state = {
84+
let mut generics = ast.generics;
85+
generics.params.insert(0, parse_quote!('__w));
86+
generics.params.insert(0, parse_quote!('__s));
87+
generics
88+
};
89+
let (
90+
user_impl_generics_with_world_and_state,
91+
user_ty_generics_with_world_and_state,
92+
user_where_clauses_with_world_and_state,
93+
) = user_generics_with_world_and_state.split_for_impl();
8494

8595
let struct_name = ast.ident;
8696
let read_only_struct_name = if attributes.is_mutable {
@@ -165,13 +175,13 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
165175
&visibility,
166176
&item_struct_name,
167177
&field_types,
168-
&user_impl_generics_with_world,
178+
&user_impl_generics_with_world_and_state,
169179
&field_attrs,
170180
&field_visibilities,
171181
&field_idents,
172182
&user_ty_generics,
173-
&user_ty_generics_with_world,
174-
user_where_clauses_with_world,
183+
&user_ty_generics_with_world_and_state,
184+
user_where_clauses_with_world_and_state,
175185
);
176186
let mutable_world_query_impl = world_query_impl(
177187
&path,
@@ -200,13 +210,13 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
200210
&visibility,
201211
&read_only_item_struct_name,
202212
&read_only_field_types,
203-
&user_impl_generics_with_world,
213+
&user_impl_generics_with_world_and_state,
204214
&field_attrs,
205215
&field_visibilities,
206216
&field_idents,
207217
&user_ty_generics,
208-
&user_ty_generics_with_world,
209-
user_where_clauses_with_world,
218+
&user_ty_generics_with_world_and_state,
219+
user_where_clauses_with_world_and_state,
210220
);
211221
let readonly_world_query_impl = world_query_impl(
212222
&path,
@@ -257,7 +267,7 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
257267
for #read_only_struct_name #user_ty_generics #user_where_clauses {
258268
const IS_READ_ONLY: bool = true;
259269
type ReadOnly = #read_only_struct_name #user_ty_generics;
260-
type Item<'__w, '__s> = #read_only_item_struct_name #user_ty_generics_with_world;
270+
type Item<'__w, '__s> = #read_only_item_struct_name #user_ty_generics_with_world_and_state;
261271

262272
fn shrink<'__wlong: '__wshort, '__wshort, '__s>(
263273
item: Self::Item<'__wlong, '__s>
@@ -280,12 +290,13 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
280290
/// SAFETY: we call `fetch` for each member that implements `Fetch`.
281291
#[inline(always)]
282292
unsafe fn fetch<'__w, '__s>(
283-
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
293+
_state: &'__s Self::State,
294+
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>,
284295
_entity: #path::entity::Entity,
285296
_table_row: #path::storage::TableRow,
286297
) -> Self::Item<'__w, '__s> {
287298
Self::Item {
288-
#(#field_idents: <#read_only_field_types>::fetch(&mut _fetch.#named_field_idents, _entity, _table_row),)*
299+
#(#field_idents: <#read_only_field_types>::fetch(&_state.#named_field_idents, &mut _fetch.#named_field_idents, _entity, _table_row),)*
289300
}
290301
}
291302
}
@@ -314,7 +325,7 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
314325
for #struct_name #user_ty_generics #user_where_clauses {
315326
const IS_READ_ONLY: bool = #is_read_only;
316327
type ReadOnly = #read_only_struct_name #user_ty_generics;
317-
type Item<'__w, '__s> = #item_struct_name #user_ty_generics_with_world;
328+
type Item<'__w, '__s> = #item_struct_name #user_ty_generics_with_world_and_state;
318329

319330
fn shrink<'__wlong: '__wshort, '__wshort, '__s>(
320331
item: Self::Item<'__wlong, '__s>
@@ -337,12 +348,13 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
337348
/// SAFETY: we call `fetch` for each member that implements `Fetch`.
338349
#[inline(always)]
339350
unsafe fn fetch<'__w, '__s>(
340-
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
351+
_state: &'__s Self::State,
352+
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>,
341353
_entity: #path::entity::Entity,
342354
_table_row: #path::storage::TableRow,
343355
) -> Self::Item<'__w, '__s> {
344356
Self::Item {
345-
#(#field_idents: <#field_types>::fetch(&mut _fetch.#named_field_idents, _entity, _table_row),)*
357+
#(#field_idents: <#field_types>::fetch(&_state.#named_field_idents, &mut _fetch.#named_field_idents, _entity, _table_row),)*
346358
}
347359
}
348360
}

crates/bevy_ecs/macros/src/query_filter.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ pub fn derive_query_filter_impl(input: TokenStream) -> TokenStream {
2323
let user_generics_with_world = {
2424
let mut generics = ast.generics;
2525
generics.params.insert(0, parse_quote!('__w));
26-
generics.params.insert(0, parse_quote!('__s));
2726
generics
2827
};
2928
let (user_impl_generics_with_world, user_ty_generics_with_world, user_where_clauses_with_world) =
@@ -102,12 +101,13 @@ pub fn derive_query_filter_impl(input: TokenStream) -> TokenStream {
102101

103102
#[allow(unused_variables)]
104103
#[inline(always)]
105-
unsafe fn filter_fetch<'__w, '__s>(
106-
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
104+
unsafe fn filter_fetch<'__w>(
105+
_state: &Self::State,
106+
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>,
107107
_entity: #path::entity::Entity,
108108
_table_row: #path::storage::TableRow,
109109
) -> bool {
110-
true #(&& <#field_types>::filter_fetch(&mut _fetch.#named_field_idents, _entity, _table_row))*
110+
true #(&& <#field_types>::filter_fetch(&_state.#named_field_idents, &mut _fetch.#named_field_idents, _entity, _table_row))*
111111
}
112112
}
113113
};

crates/bevy_ecs/macros/src/world_query.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ pub(crate) fn item_struct(
1010
visibility: &Visibility,
1111
item_struct_name: &Ident,
1212
field_types: &Vec<proc_macro2::TokenStream>,
13-
user_impl_generics_with_world: &ImplGenerics,
13+
user_impl_generics_with_world_and_state: &ImplGenerics,
1414
field_attrs: &Vec<Vec<Attribute>>,
1515
field_visibilities: &Vec<Visibility>,
1616
field_idents: &Vec<proc_macro2::TokenStream>,
1717
user_ty_generics: &TypeGenerics,
18-
user_ty_generics_with_world: &TypeGenerics,
19-
user_where_clauses_with_world: Option<&WhereClause>,
18+
user_ty_generics_with_world_and_state: &TypeGenerics,
19+
user_where_clauses_with_world_and_state: Option<&WhereClause>,
2020
) -> proc_macro2::TokenStream {
2121
let item_attrs = quote! {
2222
#[doc = concat!(
@@ -33,20 +33,20 @@ pub(crate) fn item_struct(
3333
Fields::Named(_) => quote! {
3434
#derive_macro_call
3535
#item_attrs
36-
#visibility struct #item_struct_name #user_impl_generics_with_world #user_where_clauses_with_world {
36+
#visibility struct #item_struct_name #user_impl_generics_with_world_and_state #user_where_clauses_with_world_and_state {
3737
#(#(#field_attrs)* #field_visibilities #field_idents: <#field_types as #path::query::QueryData>::Item<'__w, '__s>,)*
3838
}
3939
},
4040
Fields::Unnamed(_) => quote! {
4141
#derive_macro_call
4242
#item_attrs
43-
#visibility struct #item_struct_name #user_impl_generics_with_world #user_where_clauses_with_world(
43+
#visibility struct #item_struct_name #user_impl_generics_with_world_and_state #user_where_clauses_with_world_and_state(
4444
#( #field_visibilities <#field_types as #path::query::QueryData>::Item<'__w, '__s>, )*
4545
);
4646
},
4747
Fields::Unit => quote! {
4848
#item_attrs
49-
#visibility type #item_struct_name #user_ty_generics_with_world = #struct_name #user_ty_generics;
49+
#visibility type #item_struct_name #user_ty_generics_with_world_and_state = #struct_name #user_ty_generics;
5050
},
5151
}
5252
}
@@ -78,16 +78,16 @@ pub(crate) fn world_query_impl(
7878
)]
7979
#[automatically_derived]
8080
#visibility struct #fetch_struct_name #user_impl_generics_with_world #user_where_clauses_with_world {
81-
#(#named_field_idents: <#field_types as #path::query::WorldQuery>::Fetch<'__w, '__s>,)*
82-
#marker_name: (&'__w(), &'__s()),
81+
#(#named_field_idents: <#field_types as #path::query::WorldQuery>::Fetch<'__w>,)*
82+
#marker_name: &'__w(),
8383
}
8484

8585
impl #user_impl_generics_with_world Clone for #fetch_struct_name #user_ty_generics_with_world
8686
#user_where_clauses_with_world {
8787
fn clone(&self) -> Self {
8888
Self {
8989
#(#named_field_idents: self.#named_field_idents.clone(),)*
90-
#marker_name: (&(), &()),
90+
#marker_name: &(),
9191
}
9292
}
9393
}
@@ -96,17 +96,17 @@ pub(crate) fn world_query_impl(
9696
unsafe impl #user_impl_generics #path::query::WorldQuery
9797
for #struct_name #user_ty_generics #user_where_clauses {
9898

99-
type Fetch<'__w, '__s> = #fetch_struct_name #user_ty_generics_with_world;
99+
type Fetch<'__w> = #fetch_struct_name #user_ty_generics_with_world;
100100
type State = #state_struct_name #user_ty_generics;
101101

102-
fn shrink_fetch<'__wlong: '__wshort, '__wshort, '__s>(
103-
fetch: <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wlong, '__s>
104-
) -> <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wshort, '__s> {
102+
fn shrink_fetch<'__wlong: '__wshort, '__wshort>(
103+
fetch: <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wlong>
104+
) -> <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wshort> {
105105
#fetch_struct_name {
106106
#(
107107
#named_field_idents: <#field_types>::shrink_fetch(fetch.#named_field_idents),
108108
)*
109-
#marker_name: (&(), &()),
109+
#marker_name: &(),
110110
}
111111
}
112112

@@ -115,7 +115,7 @@ pub(crate) fn world_query_impl(
115115
state: &'__s Self::State,
116116
_last_run: #path::component::Tick,
117117
_this_run: #path::component::Tick,
118-
) -> <Self as #path::query::WorldQuery>::Fetch<'__w, '__s> {
118+
) -> <Self as #path::query::WorldQuery>::Fetch<'__w> {
119119
#fetch_struct_name {
120120
#(#named_field_idents:
121121
<#field_types>::init_fetch(
@@ -125,7 +125,7 @@ pub(crate) fn world_query_impl(
125125
_this_run,
126126
),
127127
)*
128-
#marker_name: (&(), &()),
128+
#marker_name: &(),
129129
}
130130
}
131131

@@ -134,7 +134,7 @@ pub(crate) fn world_query_impl(
134134
/// SAFETY: we call `set_archetype` for each member that implements `Fetch`
135135
#[inline]
136136
unsafe fn set_archetype<'__w, '__s>(
137-
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
137+
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>,
138138
_state: &'__s Self::State,
139139
_archetype: &'__w #path::archetype::Archetype,
140140
_table: &'__w #path::storage::Table
@@ -145,7 +145,7 @@ pub(crate) fn world_query_impl(
145145
/// SAFETY: we call `set_table` for each member that implements `Fetch`
146146
#[inline]
147147
unsafe fn set_table<'__w, '__s>(
148-
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
148+
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>,
149149
_state: &'__s Self::State,
150150
_table: &'__w #path::storage::Table
151151
) {

0 commit comments

Comments
 (0)