Skip to content

Commit a954f3e

Browse files
authored
Remove #[system_param(ignore)] and #[world_query(ignore)] (#8265)
# Objective Follow-up to #8030. Now that `SystemParam` and `WorldQuery` are implemented for `PhantomData`, the `ignore` attributes are now unnecessary. --- ## Changelog - Removed the attributes `#[system_param(ignore)]` and `#[world_query(ignore)]`. ## Migration Guide The attributes `#[system_param(ignore)]` and `#[world_query]` ignore have been removed. If you were using either of these with `PhantomData` fields, you can simply remove the attribute: ```rust #[derive(SystemParam)] struct MyParam<'w, 's, Marker> { ... // Before: #[system_param(ignore) _marker: PhantomData<Marker>, // After: _marker: PhantomData<Marker>, } #[derive(WorldQuery)] struct MyQuery<Marker> { ... // Before: #[world_query(ignore) _marker: PhantomData<Marker>, // After: _marker: PhantomData<Marker>, } ``` If you were using this for another type that implements `Default`, consider wrapping that type in `Local<>` (this only works for `SystemParam`): ```rust #[derive(SystemParam)] struct MyParam<'w, 's> { // Before: #[system_param(ignore)] value: MyDefaultType, // This will be initialized using `Default` each time `MyParam` is created. // After: value: Local<MyDefaultType>, // This will be initialized using `Default` the first time `MyParam` is created. } ``` If you are implementing either trait and need to preserve the exact behavior of the old `ignore` attributes, consider manually implementing `SystemParam` or `WorldQuery` for a wrapper struct that uses the `Default` trait: ```rust // Before: #[derive(WorldQuery) struct MyQuery { #[world_query(ignore)] str: String, } // After: #[derive(WorldQuery) struct MyQuery { str: DefaultQuery<String>, } pub struct DefaultQuery<T: Default>(pub T); unsafe impl<T: Default> WorldQuery for DefaultQuery<T> { type Item<'w> = Self; ... unsafe fn fetch<'w>(...) -> Self::Item<'w> { Self(T::default()) } } ```
1 parent 9895431 commit a954f3e

File tree

4 files changed

+46
-159
lines changed

4 files changed

+46
-159
lines changed

crates/bevy_ecs/macros/src/fetch.rs

Lines changed: 27 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -129,33 +129,24 @@ pub fn derive_world_query_impl(input: TokenStream) -> TokenStream {
129129
_ => panic!("Expected a struct with named fields"),
130130
};
131131

132-
let mut ignored_field_attrs = Vec::new();
133-
let mut ignored_field_visibilities = Vec::new();
134-
let mut ignored_field_idents = Vec::new();
135-
let mut ignored_field_types = Vec::new();
136132
let mut field_attrs = Vec::new();
137133
let mut field_visibilities = Vec::new();
138134
let mut field_idents = Vec::new();
139135
let mut field_types = Vec::new();
140136
let mut read_only_field_types = Vec::new();
141137

142138
for field in fields {
143-
let WorldQueryFieldInfo { is_ignored, attrs } = read_world_query_field_info(field);
144-
145-
let field_ident = field.ident.as_ref().unwrap().clone();
146-
if is_ignored {
147-
ignored_field_attrs.push(attrs);
148-
ignored_field_visibilities.push(field.vis.clone());
149-
ignored_field_idents.push(field_ident.clone());
150-
ignored_field_types.push(field.ty.clone());
151-
} else {
152-
field_attrs.push(attrs);
153-
field_visibilities.push(field.vis.clone());
154-
field_idents.push(field_ident.clone());
155-
let field_ty = field.ty.clone();
156-
field_types.push(quote!(#field_ty));
157-
read_only_field_types.push(quote!(<#field_ty as #path::query::WorldQuery>::ReadOnly));
158-
}
139+
let attrs = match read_world_query_field_info(field) {
140+
Ok(WorldQueryFieldInfo { attrs }) => attrs,
141+
Err(e) => return e.into_compile_error().into(),
142+
};
143+
144+
field_attrs.push(attrs);
145+
field_visibilities.push(field.vis.clone());
146+
field_idents.push(field.ident.as_ref().unwrap().clone());
147+
let field_ty = field.ty.clone();
148+
field_types.push(quote!(#field_ty));
149+
read_only_field_types.push(quote!(<#field_ty as #path::query::WorldQuery>::ReadOnly));
159150
}
160151

161152
let derive_args = &fetch_struct_attributes.derive_args;
@@ -193,7 +184,6 @@ pub fn derive_world_query_impl(input: TokenStream) -> TokenStream {
193184
#[automatically_derived]
194185
#visibility struct #item_struct_name #user_impl_generics_with_world #user_where_clauses_with_world {
195186
#(#(#field_attrs)* #field_visibilities #field_idents: <#field_types as #path::query::WorldQuery>::Item<'__w>,)*
196-
#(#(#ignored_field_attrs)* #ignored_field_visibilities #ignored_field_idents: #ignored_field_types,)*
197187
}
198188
};
199189

@@ -205,7 +195,6 @@ pub fn derive_world_query_impl(input: TokenStream) -> TokenStream {
205195
#[automatically_derived]
206196
#visibility struct #fetch_struct_name #user_impl_generics_with_world #user_where_clauses_with_world {
207197
#(#field_idents: <#field_types as #path::query::WorldQuery>::Fetch<'__w>,)*
208-
#(#ignored_field_idents: #ignored_field_types,)*
209198
}
210199

211200
// SAFETY: `update_component_access` and `update_archetype_component_access` are called on every field
@@ -224,9 +213,6 @@ pub fn derive_world_query_impl(input: TokenStream) -> TokenStream {
224213
#(
225214
#field_idents: <#field_types>::shrink(item.#field_idents),
226215
)*
227-
#(
228-
#ignored_field_idents: item.#ignored_field_idents,
229-
)*
230216
}
231217
}
232218

@@ -245,7 +231,6 @@ pub fn derive_world_query_impl(input: TokenStream) -> TokenStream {
245231
_this_run,
246232
),
247233
)*
248-
#(#ignored_field_idents: Default::default(),)*
249234
}
250235
}
251236

@@ -256,9 +241,6 @@ pub fn derive_world_query_impl(input: TokenStream) -> TokenStream {
256241
#(
257242
#field_idents: <#field_types>::clone_fetch(& _fetch. #field_idents),
258243
)*
259-
#(
260-
#ignored_field_idents: Default::default(),
261-
)*
262244
}
263245
}
264246

@@ -296,7 +278,6 @@ pub fn derive_world_query_impl(input: TokenStream) -> TokenStream {
296278
) -> <Self as #path::query::WorldQuery>::Item<'__w> {
297279
Self::Item {
298280
#(#field_idents: <#field_types>::fetch(&mut _fetch.#field_idents, _entity, _table_row),)*
299-
#(#ignored_field_idents: Default::default(),)*
300281
}
301282
}
302283

@@ -327,7 +308,6 @@ pub fn derive_world_query_impl(input: TokenStream) -> TokenStream {
327308
fn init_state(world: &mut #path::world::World) -> #state_struct_name #user_ty_generics {
328309
#state_struct_name {
329310
#(#field_idents: <#field_types>::init_state(world),)*
330-
#(#ignored_field_idents: Default::default(),)*
331311
}
332312
}
333313

@@ -349,7 +329,6 @@ pub fn derive_world_query_impl(input: TokenStream) -> TokenStream {
349329
#[automatically_derived]
350330
#visibility struct #read_only_struct_name #user_impl_generics #user_where_clauses {
351331
#( #field_visibilities #field_idents: #read_only_field_types, )*
352-
#(#(#ignored_field_attrs)* #ignored_field_visibilities #ignored_field_idents: #ignored_field_types,)*
353332
}
354333

355334
#readonly_state
@@ -396,7 +375,6 @@ pub fn derive_world_query_impl(input: TokenStream) -> TokenStream {
396375
#[automatically_derived]
397376
#visibility struct #state_struct_name #user_impl_generics #user_where_clauses {
398377
#(#field_idents: <#field_types as #path::query::WorldQuery>::State,)*
399-
#(#ignored_field_idents: ::std::marker::PhantomData<fn() -> #ignored_field_types>,)*
400378
}
401379

402380
#mutable_impl
@@ -428,56 +406,32 @@ pub fn derive_world_query_impl(input: TokenStream) -> TokenStream {
428406
q2: #read_only_struct_name #user_ty_generics
429407
) #user_where_clauses {
430408
#(q.#field_idents;)*
431-
#(q.#ignored_field_idents;)*
432409
#(q2.#field_idents;)*
433-
#(q2.#ignored_field_idents;)*
434410
}
435411
};
436412
})
437413
}
438414

439415
struct WorldQueryFieldInfo {
440-
/// Has the `#[world_query(ignore)]` attribute.
441-
is_ignored: bool,
442416
/// All field attributes except for `world_query` ones.
443417
attrs: Vec<Attribute>,
444418
}
445419

446-
fn read_world_query_field_info(field: &Field) -> WorldQueryFieldInfo {
447-
let is_ignored = field
448-
.attrs
449-
.iter()
450-
.find(|attr| {
451-
attr.path
452-
.get_ident()
453-
.map_or(false, |ident| ident == WORLD_QUERY_ATTRIBUTE_NAME)
454-
})
455-
.map_or(false, |attr| {
456-
let mut is_ignored = false;
457-
attr.parse_args_with(|input: ParseStream| {
458-
if input
459-
.parse::<Option<field_attr_keywords::ignore>>()?
460-
.is_some()
461-
{
462-
is_ignored = true;
463-
}
464-
Ok(())
465-
})
466-
.unwrap_or_else(|_| panic!("Invalid `{WORLD_QUERY_ATTRIBUTE_NAME}` attribute format"));
467-
468-
is_ignored
469-
});
470-
471-
let attrs = field
472-
.attrs
473-
.iter()
474-
.filter(|attr| {
475-
attr.path
476-
.get_ident()
477-
.map_or(true, |ident| ident != WORLD_QUERY_ATTRIBUTE_NAME)
478-
})
479-
.cloned()
480-
.collect();
420+
fn read_world_query_field_info(field: &Field) -> syn::Result<WorldQueryFieldInfo> {
421+
let mut attrs = Vec::new();
422+
for attr in &field.attrs {
423+
if attr
424+
.path
425+
.get_ident()
426+
.map_or(false, |ident| ident == WORLD_QUERY_ATTRIBUTE_NAME)
427+
{
428+
return Err(syn::Error::new_spanned(
429+
attr,
430+
"#[derive(WorldQuery)] does not support field attributes.",
431+
));
432+
}
433+
attrs.push(attr.clone());
434+
}
481435

482-
WorldQueryFieldInfo { is_ignored, attrs }
436+
Ok(WorldQueryFieldInfo { attrs })
483437
}

crates/bevy_ecs/macros/src/lib.rs

Lines changed: 13 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@ use proc_macro::TokenStream;
1313
use proc_macro2::Span;
1414
use quote::{format_ident, quote};
1515
use syn::{
16-
parse::ParseStream, parse_macro_input, parse_quote, punctuated::Punctuated, spanned::Spanned,
17-
ConstParam, DeriveInput, GenericParam, Ident, Index, Meta, MetaList, NestedMeta, Token,
18-
TypeParam,
16+
parse_macro_input, parse_quote, punctuated::Punctuated, spanned::Spanned, ConstParam,
17+
DeriveInput, GenericParam, Ident, Index, Meta, MetaList, NestedMeta, Token, TypeParam,
1918
};
2019

2120
enum BundleFieldKind {
@@ -252,13 +251,6 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream {
252251
tokens
253252
}
254253

255-
#[derive(Default)]
256-
struct SystemParamFieldAttributes {
257-
pub ignore: bool,
258-
}
259-
260-
static SYSTEM_PARAM_ATTRIBUTE_NAME: &str = "system_param";
261-
262254
/// Implement `SystemParam` to use a struct as a parameter in a system
263255
#[proc_macro_derive(SystemParam, attributes(system_param))]
264256
pub fn derive_system_param(input: TokenStream) -> TokenStream {
@@ -271,53 +263,20 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
271263
};
272264
let path = bevy_ecs_path();
273265

274-
let field_attributes = field_definitions
275-
.iter()
276-
.map(|field| {
277-
(
278-
field,
279-
field
280-
.attrs
281-
.iter()
282-
.find(|a| *a.path.get_ident().as_ref().unwrap() == SYSTEM_PARAM_ATTRIBUTE_NAME)
283-
.map_or_else(SystemParamFieldAttributes::default, |a| {
284-
syn::custom_keyword!(ignore);
285-
let mut attributes = SystemParamFieldAttributes::default();
286-
a.parse_args_with(|input: ParseStream| {
287-
if input.parse::<Option<ignore>>()?.is_some() {
288-
attributes.ignore = true;
289-
}
290-
Ok(())
291-
})
292-
.expect("Invalid 'system_param' attribute format.");
293-
294-
attributes
295-
}),
296-
)
297-
})
298-
.collect::<Vec<_>>();
299-
300266
let mut field_locals = Vec::new();
301267
let mut fields = Vec::new();
302268
let mut field_types = Vec::new();
303-
let mut ignored_fields = Vec::new();
304-
let mut ignored_field_types = Vec::new();
305-
for (i, (field, attrs)) in field_attributes.iter().enumerate() {
306-
if attrs.ignore {
307-
ignored_fields.push(field.ident.as_ref().unwrap());
308-
ignored_field_types.push(&field.ty);
309-
} else {
310-
field_locals.push(format_ident!("f{i}"));
311-
let i = Index::from(i);
312-
fields.push(
313-
field
314-
.ident
315-
.as_ref()
316-
.map(|f| quote! { #f })
317-
.unwrap_or_else(|| quote! { #i }),
318-
);
319-
field_types.push(&field.ty);
320-
}
269+
for (i, field) in field_definitions.iter().enumerate() {
270+
field_locals.push(format_ident!("f{i}"));
271+
let i = Index::from(i);
272+
fields.push(
273+
field
274+
.ident
275+
.as_ref()
276+
.map(|f| quote! { #f })
277+
.unwrap_or_else(|| quote! { #i }),
278+
);
279+
field_types.push(&field.ty);
321280
}
322281

323282
let generics = ast.generics;
@@ -383,13 +342,6 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
383342
let mut tuple_types: Vec<_> = field_types.iter().map(|x| quote! { #x }).collect();
384343
let mut tuple_patterns: Vec<_> = field_locals.iter().map(|x| quote! { #x }).collect();
385344

386-
tuple_types.extend(
387-
ignored_field_types
388-
.iter()
389-
.map(|ty| parse_quote!(::std::marker::PhantomData::<#ty>)),
390-
);
391-
tuple_patterns.extend(ignored_field_types.iter().map(|_| parse_quote!(_)));
392-
393345
// If the number of fields exceeds the 16-parameter limit,
394346
// fold the fields into tuples of tuples until we are below the limit.
395347
const LIMIT: usize = 16;
@@ -463,7 +415,6 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
463415
>::get_param(&mut state.state, system_meta, world, change_tick);
464416
#struct_name {
465417
#(#fields: #field_locals,)*
466-
#(#ignored_fields: std::default::Default::default(),)*
467418
}
468419
}
469420
}

crates/bevy_ecs/src/query/fetch.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,7 @@ use std::{cell::UnsafeCell, marker::PhantomData};
5555
/// - Methods can be implemented for the query items.
5656
/// - There is no hardcoded limit on the number of elements.
5757
///
58-
/// This trait can only be derived if each field either
59-
///
60-
/// * also implements `WorldQuery`, or
61-
/// * is marked with `#[world_query(ignore)]`. Fields decorated with this attribute
62-
/// must implement [`Default`] and will be initialized to the default value as defined
63-
/// by the trait.
64-
///
58+
/// This trait can only be derived if each field also implements `WorldQuery`.
6559
/// The derive macro only supports regular structs (structs with named fields).
6660
///
6761
/// ```
@@ -1485,9 +1479,7 @@ mod tests {
14851479
#[derive(WorldQuery)]
14861480
pub struct IgnoredQuery<Marker> {
14871481
id: Entity,
1488-
#[world_query(ignore)]
14891482
_marker: PhantomData<Marker>,
1490-
_marker2: PhantomData<Marker>,
14911483
}
14921484

14931485
fn ignored_system(_: Query<IgnoredQuery<()>>) {}

crates/bevy_ecs/src/system/system_param.rs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,10 @@ use std::{
3636
/// Derived `SystemParam` structs may have two lifetimes: `'w` for data stored in the [`World`],
3737
/// and `'s` for data stored in the parameter's state.
3838
///
39-
/// ## Attributes
39+
/// ## `PhantomData`
4040
///
41-
/// `#[system_param(ignore)]`:
42-
/// Can be added to any field in the struct. Fields decorated with this attribute
43-
/// will be created with the default value upon realisation.
44-
/// This is most useful for `PhantomData` fields, such as markers for generic types.
41+
/// [`PhantomData`] is a special type of `SystemParam` that does nothing.
42+
/// This is useful for constraining generic types or lifetimes.
4543
///
4644
/// # Example
4745
///
@@ -55,7 +53,6 @@ use std::{
5553
/// #[derive(SystemParam)]
5654
/// struct MyParam<'w, Marker: 'static> {
5755
/// foo: Res<'w, SomeResource>,
58-
/// #[system_param(ignore)]
5956
/// marker: PhantomData<Marker>,
6057
/// }
6158
///
@@ -66,11 +63,6 @@ use std::{
6663
/// # bevy_ecs::system::assert_is_system(my_system::<()>);
6764
/// ```
6865
///
69-
/// ## `PhantomData`
70-
///
71-
/// [`PhantomData`] is a special type of `SystemParam` that does nothing.
72-
/// This is useful for constraining generic types or lifetimes.
73-
///
7466
/// # Generic `SystemParam`s
7567
///
7668
/// When using the derive macro, you may see an error in the form of:
@@ -1652,14 +1644,12 @@ mod tests {
16521644
#[test]
16531645
fn system_param_phantom_data() {
16541646
#[derive(SystemParam)]
1655-
struct IgnoredParam<'w, T: Resource, Marker: 'static> {
1647+
struct PhantomParam<'w, T: Resource, Marker: 'static> {
16561648
_foo: Res<'w, T>,
1657-
#[system_param(ignore)]
16581649
marker: PhantomData<&'w Marker>,
1659-
marker2: PhantomData<&'w Marker>,
16601650
}
16611651

1662-
fn my_system(_: IgnoredParam<R<0>, ()>) {}
1652+
fn my_system(_: PhantomParam<R<0>, ()>) {}
16631653
assert_is_system(my_system);
16641654
}
16651655

0 commit comments

Comments
 (0)