Skip to content

Commit ea4d723

Browse files
Apply suggestions from code review
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
1 parent fcefa35 commit ea4d723

File tree

2 files changed

+28
-20
lines changed

2 files changed

+28
-20
lines changed

crates/bevy_ecs/macros/src/fetch.rs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,13 @@ pub fn derive_fetch_impl(input: TokenStream) -> TokenStream {
5757
quote! {}
5858
};
5959

60+
// Add `'state` and `'fetch` lifetimes that will be used in `Fetch` implementation.
6061
let mut fetch_generics = ast.generics.clone();
6162
fetch_generics.params.insert(1, state_lifetime);
62-
fetch_generics.params.push(fetch_lifetime.clone());
63+
fetch_generics.params.insert(2, fetch_lifetime.clone());
6364
let (fetch_impl_generics, _, _) = fetch_generics.split_for_impl();
6465

66+
// Replace lifetime `'world` with `'fetch`. See `replace_lifetime_for_type` for more details.
6567
let mut fetch_generics = ast.generics.clone();
6668
*fetch_generics.params.first_mut().unwrap() = fetch_lifetime;
6769
let (_, fetch_ty_generics, _) = fetch_generics.split_for_impl();
@@ -283,10 +285,11 @@ pub fn derive_filter_fetch_impl(input: TokenStream) -> TokenStream {
283285
panic!("Expected a struct without a lifetime");
284286
}
285287

288+
// Add `'world`, `'state` and `'fetch` lifetimes that will be used in `Fetch` implementation.
286289
let mut fetch_generics = ast.generics.clone();
287290
fetch_generics.params.insert(0, world_lifetime);
288291
fetch_generics.params.insert(1, state_lifetime);
289-
fetch_generics.params.push(fetch_lifetime);
292+
fetch_generics.params.insert(2, fetch_lifetime);
290293
let (fetch_impl_generics, _, _) = fetch_generics.split_for_impl();
291294

292295
let path = bevy_ecs_path();
@@ -417,19 +420,19 @@ fn fetch_impl_tokens(ast: &DeriveInput) -> FetchImplTokens {
417420
// enough to try to find a better work around, I'll leave playground links here:
418421
// - https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=da5e260a5c2f3e774142d60a199e854a (this fails)
419422
// - https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=802517bb3d8f83c45ee8c0be360bb250 (this compiles)
420-
let fetch_lifetime =
423+
let fetch_lifetime_param =
421424
GenericParam::Lifetime(LifetimeDef::new(Lifetime::new("'fetch", Span::call_site())));
422425

423426
let has_world_lifetime = world_lifetime.is_some();
424-
let world_lifetime = world_lifetime.unwrap_or_else(|| {
427+
let world_lifetime_param = world_lifetime.unwrap_or_else(|| {
425428
GenericParam::Lifetime(LifetimeDef::new(Lifetime::new("'world", Span::call_site())))
426429
});
427-
let state_lifetime =
430+
let state_lifetime_param =
428431
GenericParam::Lifetime(LifetimeDef::new(Lifetime::new("'state", Span::call_site())));
429432

430433
let mut fetch_trait_punctuated_lifetimes = Punctuated::<_, Token![,]>::new();
431-
fetch_trait_punctuated_lifetimes.push(world_lifetime.clone());
432-
fetch_trait_punctuated_lifetimes.push(state_lifetime.clone());
434+
fetch_trait_punctuated_lifetimes.push(world_lifetime_param.clone());
435+
fetch_trait_punctuated_lifetimes.push(state_lifetime_param.clone());
433436

434437
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
435438

@@ -462,13 +465,13 @@ fn fetch_impl_tokens(ast: &DeriveInput) -> FetchImplTokens {
462465
let mut query_types = Vec::new();
463466
let mut fetch_init_types = Vec::new();
464467

468+
let (world_lifetime, fetch_lifetime) = match (&world_lifetime_param, &fetch_lifetime_param) {
469+
(GenericParam::Lifetime(world), GenericParam::Lifetime(fetch)) => {
470+
(&world.lifetime, &fetch.lifetime)
471+
}
472+
_ => unreachable!(),
473+
};
465474
for field in fields.iter() {
466-
let (world_lifetime, fetch_lifetime) = match (&world_lifetime, &fetch_lifetime) {
467-
(GenericParam::Lifetime(world), GenericParam::Lifetime(fetch)) => {
468-
(&world.lifetime, &fetch.lifetime)
469-
}
470-
_ => unreachable!(),
471-
};
472475
let WorldQueryFieldTypeInfo {
473476
query_type,
474477
fetch_init_type: init_type,
@@ -499,9 +502,9 @@ fn fetch_impl_tokens(ast: &DeriveInput) -> FetchImplTokens {
499502
where_clause,
500503
has_mutable_attr,
501504
has_world_lifetime,
502-
world_lifetime,
503-
state_lifetime,
504-
fetch_lifetime,
505+
world_lifetime: world_lifetime_param,
506+
state_lifetime: state_lifetime_param,
507+
fetch_lifetime: fetch_lifetime_param,
505508
phantom_field_idents,
506509
phantom_field_types,
507510
field_idents,
@@ -527,8 +530,8 @@ fn read_world_query_field_type_info(
527530
) -> WorldQueryFieldTypeInfo {
528531
let path = bevy_ecs_path();
529532

530-
let query_type = parse_quote!(<#ty as #path::query::FetchedItem>::Query);
531-
let mut fetch_init_type = parse_quote!(<#ty as #path::query::FetchedItem>::Query);
533+
let query_type: Type = parse_quote!(<#ty as #path::query::FetchedItem>::Query);
534+
let mut fetch_init_type: Type = query_type.clone();
532535

533536
let is_phantom_data = match ty {
534537
Type::Path(path) => {
@@ -550,6 +553,11 @@ fn read_world_query_field_type_info(
550553
}
551554
}
552555

556+
// Fetch's HRTBs require substituting world lifetime with an additional one to make the
557+
// implementation compile. I don't fully understand why this works though. If anyone's curious
558+
// enough to try to find a better work around, I'll leave playground links here:
559+
// - https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=da5e260a5c2f3e774142d60a199e854a (this fails)
560+
// - https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=802517bb3d8f83c45ee8c0be360bb250 (this compiles)
553561
fn replace_lifetime_for_type(ty: &mut Type, world_lifetime: &Lifetime, fetch_lifetime: &Lifetime) {
554562
match ty {
555563
Type::Path(ref mut path) => {

crates/bevy_ecs/src/query/fetch.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub type QueryItem<'w, 's, Q> = <<Q as WorldQuery>::Fetch as Fetch<'w, 's>>::Ite
5656

5757
/// Types that appear as [`Fetch::Item`] associated types.
5858
///
59-
/// This trait comes in useful when it's needed to correlate such types as `Mut<T>` to `&mut T`.
59+
/// This trait comes in useful when it's needed to correlate between types (such as `Mut<T>` to `&mut T`).
6060
/// In most cases though, [`FetchedItem::Query`] corresponds to a type that implements the trait.
6161
pub trait FetchedItem {
6262
type Query: WorldQuery;
@@ -171,7 +171,7 @@ pub trait FetchedItem {
171171
/// ```
172172
///
173173
/// If you want to use derive macros with read-only query variants, you need to pass them with
174-
/// using the `read_only_derive` attribute. When `Fetch` macro generates an additional struct
174+
/// using the `read_only_derive` attribute. When the `Fetch` macro generates an additional struct
175175
/// for a mutable query, it doesn't automatically inherit the same derives. Since derive macros
176176
/// can't access information about other derives, they need to be passed manually with the
177177
/// `read_only_derive` attribute.

0 commit comments

Comments
 (0)