bevy/crates/bevy_derive/src/lib.rs

212 lines
5.4 KiB
Rust
Raw Normal View History

2020-01-21 11:15:28 +00:00
extern crate proc_macro;
2020-06-04 03:08:20 +00:00
mod app_plugin;
2020-11-12 21:26:48 +00:00
mod bevy_main;
bevy_derive: Add derives for `Deref` and `DerefMut` (#4328) # Objective A common pattern in Rust is the [newtype](https://doc.rust-lang.org/rust-by-example/generics/new_types.html). This is an especially useful pattern in Bevy as it allows us to give common/foreign types different semantics (such as allowing it to implement `Component` or `FromWorld`) or to simply treat them as a "new type" (clever). For example, it allows us to wrap a common `Vec<String>` and do things like: ```rust #[derive(Component)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().0.push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` > We could then define another struct that wraps `Vec<String>` without anything clashing in the query. However, one of the worst parts of this pattern is the ugly `.0` we have to write in order to access the type we actually care about. This is why people often implement `Deref` and `DerefMut` in order to get around this. Since it's such a common pattern, especially for Bevy, it makes sense to add a derive macro to automatically add those implementations. ## Solution Added a derive macro for `Deref` and another for `DerefMut` (both exported into the prelude). This works on all structs (including tuple structs) as long as they only contain a single field: ```rust #[derive(Deref)] struct Foo(String); #[derive(Deref, DerefMut)] struct Bar { name: String, } ``` This allows us to then remove that pesky `.0`: ```rust #[derive(Component, Deref, DerefMut)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` ### Alternatives There are other alternatives to this such as by using the [`derive_more`](https://crates.io/crates/derive_more) crate. However, it doesn't seem like we need an entire crate just yet since we only need `Deref` and `DerefMut` (for now). ### Considerations One thing to consider is that the Rust std library recommends _not_ using `Deref` and `DerefMut` for things like this: "`Deref` should only be implemented for smart pointers to avoid confusion" ([reference](https://doc.rust-lang.org/std/ops/trait.Deref.html)). Personally, I believe it makes sense to use it in the way described above, but others may disagree. ### Additional Context Discord: https://discord.com/channels/691052431525675048/692572690833473578/956648422163746827 (controversiality discussed [here](https://discord.com/channels/691052431525675048/692572690833473578/956711911481835630)) --- ## Changelog - Add `Deref` derive macro (exported to prelude) - Add `DerefMut` derive macro (exported to prelude) - Updated most newtypes in examples to use one or both derives Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
2022-03-29 02:10:06 +00:00
mod derefs;
mod enum_variant_meta;
2020-05-04 00:54:16 +00:00
use bevy_macro_utils::{derive_label, BevyManifest};
2020-01-19 10:02:12 +00:00
use proc_macro::TokenStream;
use quote::format_ident;
2020-03-18 23:06:33 +00:00
/// Generates a dynamic plugin entry point function for the given `Plugin` type.
2020-08-08 03:22:17 +00:00
#[proc_macro_derive(DynamicPlugin)]
pub fn derive_dynamic_plugin(input: TokenStream) -> TokenStream {
2020-08-08 03:22:17 +00:00
app_plugin::derive_dynamic_plugin(input)
2020-06-15 19:47:35 +00:00
}
bevy_derive: Add `#[deref]` attribute (#8552) # Objective Bevy code tends to make heavy use of the [newtype]( https://doc.rust-lang.org/rust-by-example/generics/new_types.html) pattern, which is why we have a dedicated derive for [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) and [`DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html). This derive works for any struct with a single field: ```rust #[derive(Component, Deref, DerefMut)] struct MyNewtype(usize); ``` One reason for the single-field limitation is to prevent confusion and footguns related that would arise from allowing multi-field structs: <table align="center"> <tr> <th colspan="2"> Similar structs, different derefs </th> </tr> <tr> <td> ```rust #[derive(Deref, DerefMut)] struct MyStruct { foo: usize, // <- Derefs usize bar: String, } ``` </td> <td> ```rust #[derive(Deref, DerefMut)] struct MyStruct { bar: String, // <- Derefs String foo: usize, } ``` </td> </tr> <tr> <th colspan="2"> Why `.1`? </th> </tr> <tr> <td colspan="2"> ```rust #[derive(Deref, DerefMut)] struct MyStruct(Vec<usize>, Vec<f32>); let mut foo = MyStruct(vec![123], vec![1.23]); // Why can we skip the `.0` here? foo.push(456); // But not here? foo.1.push(4.56); ``` </td> </tr> </table> However, there are certainly cases where it's useful to allow for structs with multiple fields. Such as for structs with one "real" field and one `PhantomData` to allow for generics: ```rust #[derive(Deref, DerefMut)] struct MyStruct<T>( // We want use this field for the `Deref`/`DerefMut` impls String, // But we need this field so that we can make this struct generic PhantomData<T> ); // ERROR: Deref can only be derived for structs with a single field // ERROR: DerefMut can only be derived for structs with a single field ``` Additionally, the possible confusion and footguns are mainly an issue for newer Rust/Bevy users. Those familiar with `Deref` and `DerefMut` understand what adding the derive really means and can anticipate its behavior. ## Solution Allow users to opt into multi-field `Deref`/`DerefMut` derives using a `#[deref]` attribute: ```rust #[derive(Deref, DerefMut)] struct MyStruct<T>( // Use this field for the `Deref`/`DerefMut` impls #[deref] String, // We can freely include any other field without a compile error PhantomData<T> ); ``` This prevents the footgun pointed out in the first issue described in the previous section, but it still leaves the possible confusion surrounding `.0`-vs-`.#`. However, the idea is that by making this behavior explicit with an attribute, users will be more aware of it and can adapt appropriately. --- ## Changelog - Added `#[deref]` attribute to `Deref` and `DerefMut` derives
2023-05-16 18:29:09 +00:00
/// Implements [`Deref`] for structs. This is especially useful when utilizing the [newtype] pattern.
///
/// For single-field structs, the implementation automatically uses that field.
/// For multi-field structs, you must specify which field to use with the `#[deref]` attribute.
bevy_derive: Add derives for `Deref` and `DerefMut` (#4328) # Objective A common pattern in Rust is the [newtype](https://doc.rust-lang.org/rust-by-example/generics/new_types.html). This is an especially useful pattern in Bevy as it allows us to give common/foreign types different semantics (such as allowing it to implement `Component` or `FromWorld`) or to simply treat them as a "new type" (clever). For example, it allows us to wrap a common `Vec<String>` and do things like: ```rust #[derive(Component)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().0.push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` > We could then define another struct that wraps `Vec<String>` without anything clashing in the query. However, one of the worst parts of this pattern is the ugly `.0` we have to write in order to access the type we actually care about. This is why people often implement `Deref` and `DerefMut` in order to get around this. Since it's such a common pattern, especially for Bevy, it makes sense to add a derive macro to automatically add those implementations. ## Solution Added a derive macro for `Deref` and another for `DerefMut` (both exported into the prelude). This works on all structs (including tuple structs) as long as they only contain a single field: ```rust #[derive(Deref)] struct Foo(String); #[derive(Deref, DerefMut)] struct Bar { name: String, } ``` This allows us to then remove that pesky `.0`: ```rust #[derive(Component, Deref, DerefMut)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` ### Alternatives There are other alternatives to this such as by using the [`derive_more`](https://crates.io/crates/derive_more) crate. However, it doesn't seem like we need an entire crate just yet since we only need `Deref` and `DerefMut` (for now). ### Considerations One thing to consider is that the Rust std library recommends _not_ using `Deref` and `DerefMut` for things like this: "`Deref` should only be implemented for smart pointers to avoid confusion" ([reference](https://doc.rust-lang.org/std/ops/trait.Deref.html)). Personally, I believe it makes sense to use it in the way described above, but others may disagree. ### Additional Context Discord: https://discord.com/channels/691052431525675048/692572690833473578/956648422163746827 (controversiality discussed [here](https://discord.com/channels/691052431525675048/692572690833473578/956711911481835630)) --- ## Changelog - Add `Deref` derive macro (exported to prelude) - Add `DerefMut` derive macro (exported to prelude) - Updated most newtypes in examples to use one or both derives Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
2022-03-29 02:10:06 +00:00
///
/// If you need [`DerefMut`] as well, consider using the other [derive] macro alongside
/// this one.
///
/// # Example
///
bevy_derive: Add `#[deref]` attribute (#8552) # Objective Bevy code tends to make heavy use of the [newtype]( https://doc.rust-lang.org/rust-by-example/generics/new_types.html) pattern, which is why we have a dedicated derive for [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) and [`DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html). This derive works for any struct with a single field: ```rust #[derive(Component, Deref, DerefMut)] struct MyNewtype(usize); ``` One reason for the single-field limitation is to prevent confusion and footguns related that would arise from allowing multi-field structs: <table align="center"> <tr> <th colspan="2"> Similar structs, different derefs </th> </tr> <tr> <td> ```rust #[derive(Deref, DerefMut)] struct MyStruct { foo: usize, // <- Derefs usize bar: String, } ``` </td> <td> ```rust #[derive(Deref, DerefMut)] struct MyStruct { bar: String, // <- Derefs String foo: usize, } ``` </td> </tr> <tr> <th colspan="2"> Why `.1`? </th> </tr> <tr> <td colspan="2"> ```rust #[derive(Deref, DerefMut)] struct MyStruct(Vec<usize>, Vec<f32>); let mut foo = MyStruct(vec![123], vec![1.23]); // Why can we skip the `.0` here? foo.push(456); // But not here? foo.1.push(4.56); ``` </td> </tr> </table> However, there are certainly cases where it's useful to allow for structs with multiple fields. Such as for structs with one "real" field and one `PhantomData` to allow for generics: ```rust #[derive(Deref, DerefMut)] struct MyStruct<T>( // We want use this field for the `Deref`/`DerefMut` impls String, // But we need this field so that we can make this struct generic PhantomData<T> ); // ERROR: Deref can only be derived for structs with a single field // ERROR: DerefMut can only be derived for structs with a single field ``` Additionally, the possible confusion and footguns are mainly an issue for newer Rust/Bevy users. Those familiar with `Deref` and `DerefMut` understand what adding the derive really means and can anticipate its behavior. ## Solution Allow users to opt into multi-field `Deref`/`DerefMut` derives using a `#[deref]` attribute: ```rust #[derive(Deref, DerefMut)] struct MyStruct<T>( // Use this field for the `Deref`/`DerefMut` impls #[deref] String, // We can freely include any other field without a compile error PhantomData<T> ); ``` This prevents the footgun pointed out in the first issue described in the previous section, but it still leaves the possible confusion surrounding `.0`-vs-`.#`. However, the idea is that by making this behavior explicit with an attribute, users will be more aware of it and can adapt appropriately. --- ## Changelog - Added `#[deref]` attribute to `Deref` and `DerefMut` derives
2023-05-16 18:29:09 +00:00
/// ## Tuple Structs
///
/// Using a single-field struct:
///
bevy_derive: Add derives for `Deref` and `DerefMut` (#4328) # Objective A common pattern in Rust is the [newtype](https://doc.rust-lang.org/rust-by-example/generics/new_types.html). This is an especially useful pattern in Bevy as it allows us to give common/foreign types different semantics (such as allowing it to implement `Component` or `FromWorld`) or to simply treat them as a "new type" (clever). For example, it allows us to wrap a common `Vec<String>` and do things like: ```rust #[derive(Component)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().0.push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` > We could then define another struct that wraps `Vec<String>` without anything clashing in the query. However, one of the worst parts of this pattern is the ugly `.0` we have to write in order to access the type we actually care about. This is why people often implement `Deref` and `DerefMut` in order to get around this. Since it's such a common pattern, especially for Bevy, it makes sense to add a derive macro to automatically add those implementations. ## Solution Added a derive macro for `Deref` and another for `DerefMut` (both exported into the prelude). This works on all structs (including tuple structs) as long as they only contain a single field: ```rust #[derive(Deref)] struct Foo(String); #[derive(Deref, DerefMut)] struct Bar { name: String, } ``` This allows us to then remove that pesky `.0`: ```rust #[derive(Component, Deref, DerefMut)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` ### Alternatives There are other alternatives to this such as by using the [`derive_more`](https://crates.io/crates/derive_more) crate. However, it doesn't seem like we need an entire crate just yet since we only need `Deref` and `DerefMut` (for now). ### Considerations One thing to consider is that the Rust std library recommends _not_ using `Deref` and `DerefMut` for things like this: "`Deref` should only be implemented for smart pointers to avoid confusion" ([reference](https://doc.rust-lang.org/std/ops/trait.Deref.html)). Personally, I believe it makes sense to use it in the way described above, but others may disagree. ### Additional Context Discord: https://discord.com/channels/691052431525675048/692572690833473578/956648422163746827 (controversiality discussed [here](https://discord.com/channels/691052431525675048/692572690833473578/956711911481835630)) --- ## Changelog - Add `Deref` derive macro (exported to prelude) - Add `DerefMut` derive macro (exported to prelude) - Updated most newtypes in examples to use one or both derives Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
2022-03-29 02:10:06 +00:00
/// ```
/// use bevy_derive::Deref;
///
/// #[derive(Deref)]
/// struct MyNewtype(String);
///
/// let foo = MyNewtype(String::from("Hello"));
bevy_derive: Add `#[deref]` attribute (#8552) # Objective Bevy code tends to make heavy use of the [newtype]( https://doc.rust-lang.org/rust-by-example/generics/new_types.html) pattern, which is why we have a dedicated derive for [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) and [`DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html). This derive works for any struct with a single field: ```rust #[derive(Component, Deref, DerefMut)] struct MyNewtype(usize); ``` One reason for the single-field limitation is to prevent confusion and footguns related that would arise from allowing multi-field structs: <table align="center"> <tr> <th colspan="2"> Similar structs, different derefs </th> </tr> <tr> <td> ```rust #[derive(Deref, DerefMut)] struct MyStruct { foo: usize, // <- Derefs usize bar: String, } ``` </td> <td> ```rust #[derive(Deref, DerefMut)] struct MyStruct { bar: String, // <- Derefs String foo: usize, } ``` </td> </tr> <tr> <th colspan="2"> Why `.1`? </th> </tr> <tr> <td colspan="2"> ```rust #[derive(Deref, DerefMut)] struct MyStruct(Vec<usize>, Vec<f32>); let mut foo = MyStruct(vec![123], vec![1.23]); // Why can we skip the `.0` here? foo.push(456); // But not here? foo.1.push(4.56); ``` </td> </tr> </table> However, there are certainly cases where it's useful to allow for structs with multiple fields. Such as for structs with one "real" field and one `PhantomData` to allow for generics: ```rust #[derive(Deref, DerefMut)] struct MyStruct<T>( // We want use this field for the `Deref`/`DerefMut` impls String, // But we need this field so that we can make this struct generic PhantomData<T> ); // ERROR: Deref can only be derived for structs with a single field // ERROR: DerefMut can only be derived for structs with a single field ``` Additionally, the possible confusion and footguns are mainly an issue for newer Rust/Bevy users. Those familiar with `Deref` and `DerefMut` understand what adding the derive really means and can anticipate its behavior. ## Solution Allow users to opt into multi-field `Deref`/`DerefMut` derives using a `#[deref]` attribute: ```rust #[derive(Deref, DerefMut)] struct MyStruct<T>( // Use this field for the `Deref`/`DerefMut` impls #[deref] String, // We can freely include any other field without a compile error PhantomData<T> ); ``` This prevents the footgun pointed out in the first issue described in the previous section, but it still leaves the possible confusion surrounding `.0`-vs-`.#`. However, the idea is that by making this behavior explicit with an attribute, users will be more aware of it and can adapt appropriately. --- ## Changelog - Added `#[deref]` attribute to `Deref` and `DerefMut` derives
2023-05-16 18:29:09 +00:00
/// assert_eq!("Hello", *foo);
/// ```
///
/// Using a multi-field struct:
///
/// ```
/// # use std::marker::PhantomData;
/// use bevy_derive::Deref;
///
/// #[derive(Deref)]
/// struct MyStruct<T>(#[deref] String, PhantomData<T>);
///
/// let foo = MyStruct(String::from("Hello"), PhantomData::<usize>);
/// assert_eq!("Hello", *foo);
/// ```
///
/// ## Named Structs
///
/// Using a single-field struct:
///
/// ```
/// use bevy_derive::{Deref, DerefMut};
///
/// #[derive(Deref, DerefMut)]
/// struct MyStruct {
/// value: String,
/// }
///
/// let foo = MyStruct {
/// value: String::from("Hello")
/// };
/// assert_eq!("Hello", *foo);
/// ```
///
/// Using a multi-field struct:
///
/// ```
/// # use std::marker::PhantomData;
/// use bevy_derive::{Deref, DerefMut};
///
/// #[derive(Deref, DerefMut)]
/// struct MyStruct<T> {
/// #[deref]
/// value: String,
/// _phantom: PhantomData<T>,
/// }
///
/// let foo = MyStruct {
/// value:String::from("Hello"),
/// _phantom:PhantomData::<usize>
/// };
/// assert_eq!("Hello", *foo);
bevy_derive: Add derives for `Deref` and `DerefMut` (#4328) # Objective A common pattern in Rust is the [newtype](https://doc.rust-lang.org/rust-by-example/generics/new_types.html). This is an especially useful pattern in Bevy as it allows us to give common/foreign types different semantics (such as allowing it to implement `Component` or `FromWorld`) or to simply treat them as a "new type" (clever). For example, it allows us to wrap a common `Vec<String>` and do things like: ```rust #[derive(Component)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().0.push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` > We could then define another struct that wraps `Vec<String>` without anything clashing in the query. However, one of the worst parts of this pattern is the ugly `.0` we have to write in order to access the type we actually care about. This is why people often implement `Deref` and `DerefMut` in order to get around this. Since it's such a common pattern, especially for Bevy, it makes sense to add a derive macro to automatically add those implementations. ## Solution Added a derive macro for `Deref` and another for `DerefMut` (both exported into the prelude). This works on all structs (including tuple structs) as long as they only contain a single field: ```rust #[derive(Deref)] struct Foo(String); #[derive(Deref, DerefMut)] struct Bar { name: String, } ``` This allows us to then remove that pesky `.0`: ```rust #[derive(Component, Deref, DerefMut)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` ### Alternatives There are other alternatives to this such as by using the [`derive_more`](https://crates.io/crates/derive_more) crate. However, it doesn't seem like we need an entire crate just yet since we only need `Deref` and `DerefMut` (for now). ### Considerations One thing to consider is that the Rust std library recommends _not_ using `Deref` and `DerefMut` for things like this: "`Deref` should only be implemented for smart pointers to avoid confusion" ([reference](https://doc.rust-lang.org/std/ops/trait.Deref.html)). Personally, I believe it makes sense to use it in the way described above, but others may disagree. ### Additional Context Discord: https://discord.com/channels/691052431525675048/692572690833473578/956648422163746827 (controversiality discussed [here](https://discord.com/channels/691052431525675048/692572690833473578/956711911481835630)) --- ## Changelog - Add `Deref` derive macro (exported to prelude) - Add `DerefMut` derive macro (exported to prelude) - Updated most newtypes in examples to use one or both derives Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
2022-03-29 02:10:06 +00:00
/// ```
///
/// [`Deref`]: std::ops::Deref
/// [newtype]: https://doc.rust-lang.org/rust-by-example/generics/new_types.html
/// [`DerefMut`]: std::ops::DerefMut
/// [derive]: crate::derive_deref_mut
bevy_derive: Add `#[deref]` attribute (#8552) # Objective Bevy code tends to make heavy use of the [newtype]( https://doc.rust-lang.org/rust-by-example/generics/new_types.html) pattern, which is why we have a dedicated derive for [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) and [`DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html). This derive works for any struct with a single field: ```rust #[derive(Component, Deref, DerefMut)] struct MyNewtype(usize); ``` One reason for the single-field limitation is to prevent confusion and footguns related that would arise from allowing multi-field structs: <table align="center"> <tr> <th colspan="2"> Similar structs, different derefs </th> </tr> <tr> <td> ```rust #[derive(Deref, DerefMut)] struct MyStruct { foo: usize, // <- Derefs usize bar: String, } ``` </td> <td> ```rust #[derive(Deref, DerefMut)] struct MyStruct { bar: String, // <- Derefs String foo: usize, } ``` </td> </tr> <tr> <th colspan="2"> Why `.1`? </th> </tr> <tr> <td colspan="2"> ```rust #[derive(Deref, DerefMut)] struct MyStruct(Vec<usize>, Vec<f32>); let mut foo = MyStruct(vec![123], vec![1.23]); // Why can we skip the `.0` here? foo.push(456); // But not here? foo.1.push(4.56); ``` </td> </tr> </table> However, there are certainly cases where it's useful to allow for structs with multiple fields. Such as for structs with one "real" field and one `PhantomData` to allow for generics: ```rust #[derive(Deref, DerefMut)] struct MyStruct<T>( // We want use this field for the `Deref`/`DerefMut` impls String, // But we need this field so that we can make this struct generic PhantomData<T> ); // ERROR: Deref can only be derived for structs with a single field // ERROR: DerefMut can only be derived for structs with a single field ``` Additionally, the possible confusion and footguns are mainly an issue for newer Rust/Bevy users. Those familiar with `Deref` and `DerefMut` understand what adding the derive really means and can anticipate its behavior. ## Solution Allow users to opt into multi-field `Deref`/`DerefMut` derives using a `#[deref]` attribute: ```rust #[derive(Deref, DerefMut)] struct MyStruct<T>( // Use this field for the `Deref`/`DerefMut` impls #[deref] String, // We can freely include any other field without a compile error PhantomData<T> ); ``` This prevents the footgun pointed out in the first issue described in the previous section, but it still leaves the possible confusion surrounding `.0`-vs-`.#`. However, the idea is that by making this behavior explicit with an attribute, users will be more aware of it and can adapt appropriately. --- ## Changelog - Added `#[deref]` attribute to `Deref` and `DerefMut` derives
2023-05-16 18:29:09 +00:00
#[proc_macro_derive(Deref, attributes(deref))]
bevy_derive: Add derives for `Deref` and `DerefMut` (#4328) # Objective A common pattern in Rust is the [newtype](https://doc.rust-lang.org/rust-by-example/generics/new_types.html). This is an especially useful pattern in Bevy as it allows us to give common/foreign types different semantics (such as allowing it to implement `Component` or `FromWorld`) or to simply treat them as a "new type" (clever). For example, it allows us to wrap a common `Vec<String>` and do things like: ```rust #[derive(Component)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().0.push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` > We could then define another struct that wraps `Vec<String>` without anything clashing in the query. However, one of the worst parts of this pattern is the ugly `.0` we have to write in order to access the type we actually care about. This is why people often implement `Deref` and `DerefMut` in order to get around this. Since it's such a common pattern, especially for Bevy, it makes sense to add a derive macro to automatically add those implementations. ## Solution Added a derive macro for `Deref` and another for `DerefMut` (both exported into the prelude). This works on all structs (including tuple structs) as long as they only contain a single field: ```rust #[derive(Deref)] struct Foo(String); #[derive(Deref, DerefMut)] struct Bar { name: String, } ``` This allows us to then remove that pesky `.0`: ```rust #[derive(Component, Deref, DerefMut)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` ### Alternatives There are other alternatives to this such as by using the [`derive_more`](https://crates.io/crates/derive_more) crate. However, it doesn't seem like we need an entire crate just yet since we only need `Deref` and `DerefMut` (for now). ### Considerations One thing to consider is that the Rust std library recommends _not_ using `Deref` and `DerefMut` for things like this: "`Deref` should only be implemented for smart pointers to avoid confusion" ([reference](https://doc.rust-lang.org/std/ops/trait.Deref.html)). Personally, I believe it makes sense to use it in the way described above, but others may disagree. ### Additional Context Discord: https://discord.com/channels/691052431525675048/692572690833473578/956648422163746827 (controversiality discussed [here](https://discord.com/channels/691052431525675048/692572690833473578/956711911481835630)) --- ## Changelog - Add `Deref` derive macro (exported to prelude) - Add `DerefMut` derive macro (exported to prelude) - Updated most newtypes in examples to use one or both derives Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
2022-03-29 02:10:06 +00:00
pub fn derive_deref(input: TokenStream) -> TokenStream {
derefs::derive_deref(input)
}
bevy_derive: Add `#[deref]` attribute (#8552) # Objective Bevy code tends to make heavy use of the [newtype]( https://doc.rust-lang.org/rust-by-example/generics/new_types.html) pattern, which is why we have a dedicated derive for [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) and [`DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html). This derive works for any struct with a single field: ```rust #[derive(Component, Deref, DerefMut)] struct MyNewtype(usize); ``` One reason for the single-field limitation is to prevent confusion and footguns related that would arise from allowing multi-field structs: <table align="center"> <tr> <th colspan="2"> Similar structs, different derefs </th> </tr> <tr> <td> ```rust #[derive(Deref, DerefMut)] struct MyStruct { foo: usize, // <- Derefs usize bar: String, } ``` </td> <td> ```rust #[derive(Deref, DerefMut)] struct MyStruct { bar: String, // <- Derefs String foo: usize, } ``` </td> </tr> <tr> <th colspan="2"> Why `.1`? </th> </tr> <tr> <td colspan="2"> ```rust #[derive(Deref, DerefMut)] struct MyStruct(Vec<usize>, Vec<f32>); let mut foo = MyStruct(vec![123], vec![1.23]); // Why can we skip the `.0` here? foo.push(456); // But not here? foo.1.push(4.56); ``` </td> </tr> </table> However, there are certainly cases where it's useful to allow for structs with multiple fields. Such as for structs with one "real" field and one `PhantomData` to allow for generics: ```rust #[derive(Deref, DerefMut)] struct MyStruct<T>( // We want use this field for the `Deref`/`DerefMut` impls String, // But we need this field so that we can make this struct generic PhantomData<T> ); // ERROR: Deref can only be derived for structs with a single field // ERROR: DerefMut can only be derived for structs with a single field ``` Additionally, the possible confusion and footguns are mainly an issue for newer Rust/Bevy users. Those familiar with `Deref` and `DerefMut` understand what adding the derive really means and can anticipate its behavior. ## Solution Allow users to opt into multi-field `Deref`/`DerefMut` derives using a `#[deref]` attribute: ```rust #[derive(Deref, DerefMut)] struct MyStruct<T>( // Use this field for the `Deref`/`DerefMut` impls #[deref] String, // We can freely include any other field without a compile error PhantomData<T> ); ``` This prevents the footgun pointed out in the first issue described in the previous section, but it still leaves the possible confusion surrounding `.0`-vs-`.#`. However, the idea is that by making this behavior explicit with an attribute, users will be more aware of it and can adapt appropriately. --- ## Changelog - Added `#[deref]` attribute to `Deref` and `DerefMut` derives
2023-05-16 18:29:09 +00:00
/// Implements [`DerefMut`] for structs. This is especially useful when utilizing the [newtype] pattern.
///
/// For single-field structs, the implementation automatically uses that field.
/// For multi-field structs, you must specify which field to use with the `#[deref]` attribute.
bevy_derive: Add derives for `Deref` and `DerefMut` (#4328) # Objective A common pattern in Rust is the [newtype](https://doc.rust-lang.org/rust-by-example/generics/new_types.html). This is an especially useful pattern in Bevy as it allows us to give common/foreign types different semantics (such as allowing it to implement `Component` or `FromWorld`) or to simply treat them as a "new type" (clever). For example, it allows us to wrap a common `Vec<String>` and do things like: ```rust #[derive(Component)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().0.push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` > We could then define another struct that wraps `Vec<String>` without anything clashing in the query. However, one of the worst parts of this pattern is the ugly `.0` we have to write in order to access the type we actually care about. This is why people often implement `Deref` and `DerefMut` in order to get around this. Since it's such a common pattern, especially for Bevy, it makes sense to add a derive macro to automatically add those implementations. ## Solution Added a derive macro for `Deref` and another for `DerefMut` (both exported into the prelude). This works on all structs (including tuple structs) as long as they only contain a single field: ```rust #[derive(Deref)] struct Foo(String); #[derive(Deref, DerefMut)] struct Bar { name: String, } ``` This allows us to then remove that pesky `.0`: ```rust #[derive(Component, Deref, DerefMut)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` ### Alternatives There are other alternatives to this such as by using the [`derive_more`](https://crates.io/crates/derive_more) crate. However, it doesn't seem like we need an entire crate just yet since we only need `Deref` and `DerefMut` (for now). ### Considerations One thing to consider is that the Rust std library recommends _not_ using `Deref` and `DerefMut` for things like this: "`Deref` should only be implemented for smart pointers to avoid confusion" ([reference](https://doc.rust-lang.org/std/ops/trait.Deref.html)). Personally, I believe it makes sense to use it in the way described above, but others may disagree. ### Additional Context Discord: https://discord.com/channels/691052431525675048/692572690833473578/956648422163746827 (controversiality discussed [here](https://discord.com/channels/691052431525675048/692572690833473578/956711911481835630)) --- ## Changelog - Add `Deref` derive macro (exported to prelude) - Add `DerefMut` derive macro (exported to prelude) - Updated most newtypes in examples to use one or both derives Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
2022-03-29 02:10:06 +00:00
///
/// [`DerefMut`] requires a [`Deref`] implementation. You can implement it manually or use
/// Bevy's [derive] macro for convenience.
///
/// # Example
///
bevy_derive: Add `#[deref]` attribute (#8552) # Objective Bevy code tends to make heavy use of the [newtype]( https://doc.rust-lang.org/rust-by-example/generics/new_types.html) pattern, which is why we have a dedicated derive for [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) and [`DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html). This derive works for any struct with a single field: ```rust #[derive(Component, Deref, DerefMut)] struct MyNewtype(usize); ``` One reason for the single-field limitation is to prevent confusion and footguns related that would arise from allowing multi-field structs: <table align="center"> <tr> <th colspan="2"> Similar structs, different derefs </th> </tr> <tr> <td> ```rust #[derive(Deref, DerefMut)] struct MyStruct { foo: usize, // <- Derefs usize bar: String, } ``` </td> <td> ```rust #[derive(Deref, DerefMut)] struct MyStruct { bar: String, // <- Derefs String foo: usize, } ``` </td> </tr> <tr> <th colspan="2"> Why `.1`? </th> </tr> <tr> <td colspan="2"> ```rust #[derive(Deref, DerefMut)] struct MyStruct(Vec<usize>, Vec<f32>); let mut foo = MyStruct(vec![123], vec![1.23]); // Why can we skip the `.0` here? foo.push(456); // But not here? foo.1.push(4.56); ``` </td> </tr> </table> However, there are certainly cases where it's useful to allow for structs with multiple fields. Such as for structs with one "real" field and one `PhantomData` to allow for generics: ```rust #[derive(Deref, DerefMut)] struct MyStruct<T>( // We want use this field for the `Deref`/`DerefMut` impls String, // But we need this field so that we can make this struct generic PhantomData<T> ); // ERROR: Deref can only be derived for structs with a single field // ERROR: DerefMut can only be derived for structs with a single field ``` Additionally, the possible confusion and footguns are mainly an issue for newer Rust/Bevy users. Those familiar with `Deref` and `DerefMut` understand what adding the derive really means and can anticipate its behavior. ## Solution Allow users to opt into multi-field `Deref`/`DerefMut` derives using a `#[deref]` attribute: ```rust #[derive(Deref, DerefMut)] struct MyStruct<T>( // Use this field for the `Deref`/`DerefMut` impls #[deref] String, // We can freely include any other field without a compile error PhantomData<T> ); ``` This prevents the footgun pointed out in the first issue described in the previous section, but it still leaves the possible confusion surrounding `.0`-vs-`.#`. However, the idea is that by making this behavior explicit with an attribute, users will be more aware of it and can adapt appropriately. --- ## Changelog - Added `#[deref]` attribute to `Deref` and `DerefMut` derives
2023-05-16 18:29:09 +00:00
/// ## Tuple Structs
///
/// Using a single-field struct:
///
bevy_derive: Add derives for `Deref` and `DerefMut` (#4328) # Objective A common pattern in Rust is the [newtype](https://doc.rust-lang.org/rust-by-example/generics/new_types.html). This is an especially useful pattern in Bevy as it allows us to give common/foreign types different semantics (such as allowing it to implement `Component` or `FromWorld`) or to simply treat them as a "new type" (clever). For example, it allows us to wrap a common `Vec<String>` and do things like: ```rust #[derive(Component)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().0.push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` > We could then define another struct that wraps `Vec<String>` without anything clashing in the query. However, one of the worst parts of this pattern is the ugly `.0` we have to write in order to access the type we actually care about. This is why people often implement `Deref` and `DerefMut` in order to get around this. Since it's such a common pattern, especially for Bevy, it makes sense to add a derive macro to automatically add those implementations. ## Solution Added a derive macro for `Deref` and another for `DerefMut` (both exported into the prelude). This works on all structs (including tuple structs) as long as they only contain a single field: ```rust #[derive(Deref)] struct Foo(String); #[derive(Deref, DerefMut)] struct Bar { name: String, } ``` This allows us to then remove that pesky `.0`: ```rust #[derive(Component, Deref, DerefMut)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` ### Alternatives There are other alternatives to this such as by using the [`derive_more`](https://crates.io/crates/derive_more) crate. However, it doesn't seem like we need an entire crate just yet since we only need `Deref` and `DerefMut` (for now). ### Considerations One thing to consider is that the Rust std library recommends _not_ using `Deref` and `DerefMut` for things like this: "`Deref` should only be implemented for smart pointers to avoid confusion" ([reference](https://doc.rust-lang.org/std/ops/trait.Deref.html)). Personally, I believe it makes sense to use it in the way described above, but others may disagree. ### Additional Context Discord: https://discord.com/channels/691052431525675048/692572690833473578/956648422163746827 (controversiality discussed [here](https://discord.com/channels/691052431525675048/692572690833473578/956711911481835630)) --- ## Changelog - Add `Deref` derive macro (exported to prelude) - Add `DerefMut` derive macro (exported to prelude) - Updated most newtypes in examples to use one or both derives Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
2022-03-29 02:10:06 +00:00
/// ```
/// use bevy_derive::{Deref, DerefMut};
///
/// #[derive(Deref, DerefMut)]
/// struct MyNewtype(String);
///
/// let mut foo = MyNewtype(String::from("Hello"));
/// foo.push_str(" World!");
/// assert_eq!("Hello World!", *foo);
/// ```
///
bevy_derive: Add `#[deref]` attribute (#8552) # Objective Bevy code tends to make heavy use of the [newtype]( https://doc.rust-lang.org/rust-by-example/generics/new_types.html) pattern, which is why we have a dedicated derive for [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) and [`DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html). This derive works for any struct with a single field: ```rust #[derive(Component, Deref, DerefMut)] struct MyNewtype(usize); ``` One reason for the single-field limitation is to prevent confusion and footguns related that would arise from allowing multi-field structs: <table align="center"> <tr> <th colspan="2"> Similar structs, different derefs </th> </tr> <tr> <td> ```rust #[derive(Deref, DerefMut)] struct MyStruct { foo: usize, // <- Derefs usize bar: String, } ``` </td> <td> ```rust #[derive(Deref, DerefMut)] struct MyStruct { bar: String, // <- Derefs String foo: usize, } ``` </td> </tr> <tr> <th colspan="2"> Why `.1`? </th> </tr> <tr> <td colspan="2"> ```rust #[derive(Deref, DerefMut)] struct MyStruct(Vec<usize>, Vec<f32>); let mut foo = MyStruct(vec![123], vec![1.23]); // Why can we skip the `.0` here? foo.push(456); // But not here? foo.1.push(4.56); ``` </td> </tr> </table> However, there are certainly cases where it's useful to allow for structs with multiple fields. Such as for structs with one "real" field and one `PhantomData` to allow for generics: ```rust #[derive(Deref, DerefMut)] struct MyStruct<T>( // We want use this field for the `Deref`/`DerefMut` impls String, // But we need this field so that we can make this struct generic PhantomData<T> ); // ERROR: Deref can only be derived for structs with a single field // ERROR: DerefMut can only be derived for structs with a single field ``` Additionally, the possible confusion and footguns are mainly an issue for newer Rust/Bevy users. Those familiar with `Deref` and `DerefMut` understand what adding the derive really means and can anticipate its behavior. ## Solution Allow users to opt into multi-field `Deref`/`DerefMut` derives using a `#[deref]` attribute: ```rust #[derive(Deref, DerefMut)] struct MyStruct<T>( // Use this field for the `Deref`/`DerefMut` impls #[deref] String, // We can freely include any other field without a compile error PhantomData<T> ); ``` This prevents the footgun pointed out in the first issue described in the previous section, but it still leaves the possible confusion surrounding `.0`-vs-`.#`. However, the idea is that by making this behavior explicit with an attribute, users will be more aware of it and can adapt appropriately. --- ## Changelog - Added `#[deref]` attribute to `Deref` and `DerefMut` derives
2023-05-16 18:29:09 +00:00
/// Using a multi-field struct:
///
/// ```
/// # use std::marker::PhantomData;
/// use bevy_derive::{Deref, DerefMut};
///
/// #[derive(Deref, DerefMut)]
/// struct MyStruct<T>(#[deref] String, PhantomData<T>);
///
/// let mut foo = MyStruct(String::from("Hello"), PhantomData::<usize>);
/// foo.push_str(" World!");
/// assert_eq!("Hello World!", *foo);
/// ```
///
/// ## Named Structs
///
/// Using a single-field struct:
///
/// ```
/// use bevy_derive::{Deref, DerefMut};
///
/// #[derive(Deref, DerefMut)]
/// struct MyStruct {
/// value: String,
/// }
///
/// let mut foo = MyStruct {
/// value: String::from("Hello")
/// };
/// foo.push_str(" World!");
/// assert_eq!("Hello World!", *foo);
/// ```
///
/// Using a multi-field struct:
///
/// ```
/// # use std::marker::PhantomData;
/// use bevy_derive::{Deref, DerefMut};
///
/// #[derive(Deref, DerefMut)]
/// struct MyStruct<T> {
/// #[deref]
/// value: String,
/// _phantom: PhantomData<T>,
/// }
///
/// let mut foo = MyStruct {
/// value:String::from("Hello"),
/// _phantom:PhantomData::<usize>
/// };
/// foo.push_str(" World!");
/// assert_eq!("Hello World!", *foo);
/// ```
///
bevy_derive: Add derives for `Deref` and `DerefMut` (#4328) # Objective A common pattern in Rust is the [newtype](https://doc.rust-lang.org/rust-by-example/generics/new_types.html). This is an especially useful pattern in Bevy as it allows us to give common/foreign types different semantics (such as allowing it to implement `Component` or `FromWorld`) or to simply treat them as a "new type" (clever). For example, it allows us to wrap a common `Vec<String>` and do things like: ```rust #[derive(Component)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().0.push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` > We could then define another struct that wraps `Vec<String>` without anything clashing in the query. However, one of the worst parts of this pattern is the ugly `.0` we have to write in order to access the type we actually care about. This is why people often implement `Deref` and `DerefMut` in order to get around this. Since it's such a common pattern, especially for Bevy, it makes sense to add a derive macro to automatically add those implementations. ## Solution Added a derive macro for `Deref` and another for `DerefMut` (both exported into the prelude). This works on all structs (including tuple structs) as long as they only contain a single field: ```rust #[derive(Deref)] struct Foo(String); #[derive(Deref, DerefMut)] struct Bar { name: String, } ``` This allows us to then remove that pesky `.0`: ```rust #[derive(Component, Deref, DerefMut)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` ### Alternatives There are other alternatives to this such as by using the [`derive_more`](https://crates.io/crates/derive_more) crate. However, it doesn't seem like we need an entire crate just yet since we only need `Deref` and `DerefMut` (for now). ### Considerations One thing to consider is that the Rust std library recommends _not_ using `Deref` and `DerefMut` for things like this: "`Deref` should only be implemented for smart pointers to avoid confusion" ([reference](https://doc.rust-lang.org/std/ops/trait.Deref.html)). Personally, I believe it makes sense to use it in the way described above, but others may disagree. ### Additional Context Discord: https://discord.com/channels/691052431525675048/692572690833473578/956648422163746827 (controversiality discussed [here](https://discord.com/channels/691052431525675048/692572690833473578/956711911481835630)) --- ## Changelog - Add `Deref` derive macro (exported to prelude) - Add `DerefMut` derive macro (exported to prelude) - Updated most newtypes in examples to use one or both derives Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
2022-03-29 02:10:06 +00:00
/// [`DerefMut`]: std::ops::DerefMut
/// [newtype]: https://doc.rust-lang.org/rust-by-example/generics/new_types.html
/// [`Deref`]: std::ops::Deref
/// [derive]: crate::derive_deref
bevy_derive: Add `#[deref]` attribute (#8552) # Objective Bevy code tends to make heavy use of the [newtype]( https://doc.rust-lang.org/rust-by-example/generics/new_types.html) pattern, which is why we have a dedicated derive for [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) and [`DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html). This derive works for any struct with a single field: ```rust #[derive(Component, Deref, DerefMut)] struct MyNewtype(usize); ``` One reason for the single-field limitation is to prevent confusion and footguns related that would arise from allowing multi-field structs: <table align="center"> <tr> <th colspan="2"> Similar structs, different derefs </th> </tr> <tr> <td> ```rust #[derive(Deref, DerefMut)] struct MyStruct { foo: usize, // <- Derefs usize bar: String, } ``` </td> <td> ```rust #[derive(Deref, DerefMut)] struct MyStruct { bar: String, // <- Derefs String foo: usize, } ``` </td> </tr> <tr> <th colspan="2"> Why `.1`? </th> </tr> <tr> <td colspan="2"> ```rust #[derive(Deref, DerefMut)] struct MyStruct(Vec<usize>, Vec<f32>); let mut foo = MyStruct(vec![123], vec![1.23]); // Why can we skip the `.0` here? foo.push(456); // But not here? foo.1.push(4.56); ``` </td> </tr> </table> However, there are certainly cases where it's useful to allow for structs with multiple fields. Such as for structs with one "real" field and one `PhantomData` to allow for generics: ```rust #[derive(Deref, DerefMut)] struct MyStruct<T>( // We want use this field for the `Deref`/`DerefMut` impls String, // But we need this field so that we can make this struct generic PhantomData<T> ); // ERROR: Deref can only be derived for structs with a single field // ERROR: DerefMut can only be derived for structs with a single field ``` Additionally, the possible confusion and footguns are mainly an issue for newer Rust/Bevy users. Those familiar with `Deref` and `DerefMut` understand what adding the derive really means and can anticipate its behavior. ## Solution Allow users to opt into multi-field `Deref`/`DerefMut` derives using a `#[deref]` attribute: ```rust #[derive(Deref, DerefMut)] struct MyStruct<T>( // Use this field for the `Deref`/`DerefMut` impls #[deref] String, // We can freely include any other field without a compile error PhantomData<T> ); ``` This prevents the footgun pointed out in the first issue described in the previous section, but it still leaves the possible confusion surrounding `.0`-vs-`.#`. However, the idea is that by making this behavior explicit with an attribute, users will be more aware of it and can adapt appropriately. --- ## Changelog - Added `#[deref]` attribute to `Deref` and `DerefMut` derives
2023-05-16 18:29:09 +00:00
#[proc_macro_derive(DerefMut, attributes(deref))]
bevy_derive: Add derives for `Deref` and `DerefMut` (#4328) # Objective A common pattern in Rust is the [newtype](https://doc.rust-lang.org/rust-by-example/generics/new_types.html). This is an especially useful pattern in Bevy as it allows us to give common/foreign types different semantics (such as allowing it to implement `Component` or `FromWorld`) or to simply treat them as a "new type" (clever). For example, it allows us to wrap a common `Vec<String>` and do things like: ```rust #[derive(Component)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().0.push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` > We could then define another struct that wraps `Vec<String>` without anything clashing in the query. However, one of the worst parts of this pattern is the ugly `.0` we have to write in order to access the type we actually care about. This is why people often implement `Deref` and `DerefMut` in order to get around this. Since it's such a common pattern, especially for Bevy, it makes sense to add a derive macro to automatically add those implementations. ## Solution Added a derive macro for `Deref` and another for `DerefMut` (both exported into the prelude). This works on all structs (including tuple structs) as long as they only contain a single field: ```rust #[derive(Deref)] struct Foo(String); #[derive(Deref, DerefMut)] struct Bar { name: String, } ``` This allows us to then remove that pesky `.0`: ```rust #[derive(Component, Deref, DerefMut)] struct Items(Vec<String>); fn give_sword(query: Query<&mut Items>) { query.single_mut().push(String::from("Flaming Poisoning Raging Sword of Doom")); } ``` ### Alternatives There are other alternatives to this such as by using the [`derive_more`](https://crates.io/crates/derive_more) crate. However, it doesn't seem like we need an entire crate just yet since we only need `Deref` and `DerefMut` (for now). ### Considerations One thing to consider is that the Rust std library recommends _not_ using `Deref` and `DerefMut` for things like this: "`Deref` should only be implemented for smart pointers to avoid confusion" ([reference](https://doc.rust-lang.org/std/ops/trait.Deref.html)). Personally, I believe it makes sense to use it in the way described above, but others may disagree. ### Additional Context Discord: https://discord.com/channels/691052431525675048/692572690833473578/956648422163746827 (controversiality discussed [here](https://discord.com/channels/691052431525675048/692572690833473578/956711911481835630)) --- ## Changelog - Add `Deref` derive macro (exported to prelude) - Add `DerefMut` derive macro (exported to prelude) - Updated most newtypes in examples to use one or both derives Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
2022-03-29 02:10:06 +00:00
pub fn derive_deref_mut(input: TokenStream) -> TokenStream {
derefs::derive_deref_mut(input)
}
2020-11-12 21:26:48 +00:00
#[proc_macro_attribute]
pub fn bevy_main(attr: TokenStream, item: TokenStream) -> TokenStream {
bevy_main::bevy_main(attr, item)
}
#[proc_macro_derive(EnumVariantMeta)]
pub fn derive_enum_variant_meta(input: TokenStream) -> TokenStream {
enum_variant_meta::derive_enum_variant_meta(input)
}
Add attribute to ignore fields of derived labels (#5366) # Objective Fixes #5362 ## Solution Add the attribute `#[label(ignore_fields)]` for `*Label` types. ```rust #[derive(SystemLabel)] pub enum MyLabel { One, // Previously this was not allowed since labels cannot contain data. #[system_label(ignore_fields)] Two(PhantomData<usize>), } ``` ## Notes This label makes it possible for equality to behave differently depending on whether or not you are treating the type as a label. For example: ```rust #[derive(SystemLabel, PartialEq, Eq)] #[system_label(ignore_fields)] pub struct Foo(usize); ``` If you compare it as a label, it will ignore the wrapped fields as the user requested. But if you compare it as a `Foo`, the derive will incorrectly compare the inner fields. I see a few solutions 1. Do nothing. This is technically intended behavior, but I think we should do our best to prevent footguns. 2. Generate impls of `PartialEq` and `Eq` along with the `#[derive(Label)]` macros. This is a breaking change as it requires all users to remove these derives from their types. 3. Only allow `PhantomData` to be used with `ignore_fields` -- seems needlessly prescriptive. --- ## Changelog * Added the `ignore_fields` attribute to the derive macros for `*Label` types. * Added an example showing off different forms of the derive macro. <!-- ## Migration Guide > This section is optional. If there are no breaking changes, you can delete this section. - If this PR is a breaking change (relative to the last release of Bevy), describe how a user might need to migrate their code to support these changes - Simply adding new functionality is not a breaking change. - Fixing behavior that was definitely a bug, rather than a questionable design choice is not a breaking change. -->
2022-07-19 05:21:19 +00:00
/// Generates an impl of the `AppLabel` trait.
///
Replace all labels with interned labels (#7762) # Objective First of all, this PR took heavy inspiration from #7760 and #5715. It intends to also fix #5569, but with a slightly different approach. This also fixes #9335 by reexporting `DynEq`. ## Solution The advantage of this API is that we can intern a value without allocating for zero-sized-types and for enum variants that have no fields. This PR does this automatically in the `SystemSet` and `ScheduleLabel` derive macros for unit structs and fieldless enum variants. So this should cover many internal and external use cases of `SystemSet` and `ScheduleLabel`. In these optimal use cases, no memory will be allocated. - The interning returns a `Interned<dyn SystemSet>`, which is just a wrapper around a `&'static dyn SystemSet`. - `Hash` and `Eq` are implemented in terms of the pointer value of the reference, similar to my first approach of anonymous system sets in #7676. - Therefore, `Interned<T>` does not implement `Borrow<T>`, only `Deref`. - The debug output of `Interned<T>` is the same as the interned value. Edit: - `AppLabel` is now also interned and the old `derive_label`/`define_label` macros were replaced with the new interning implementation. - Anonymous set ids are reused for different `Schedule`s, reducing the amount of leaked memory. ### Pros - `InternedSystemSet` and `InternedScheduleLabel` behave very similar to the current `BoxedSystemSet` and `BoxedScheduleLabel`, but can be copied without an allocation. - Many use cases don't allocate at all. - Very fast lookups and comparisons when using `InternedSystemSet` and `InternedScheduleLabel`. - The `intern` module might be usable in other areas. - `Interned{ScheduleLabel, SystemSet, AppLabel}` does implement `{ScheduleLabel, SystemSet, AppLabel}`, increasing ergonomics. ### Cons - Implementors of `SystemSet` and `ScheduleLabel` still need to implement `Hash` and `Eq` (and `Clone`) for it to work. ## Changelog ### Added - Added `intern` module to `bevy_utils`. - Added reexports of `DynEq` to `bevy_ecs` and `bevy_app`. ### Changed - Replaced `BoxedSystemSet` and `BoxedScheduleLabel` with `InternedSystemSet` and `InternedScheduleLabel`. - Replaced `impl AsRef<dyn ScheduleLabel>` with `impl ScheduleLabel`. - Replaced `AppLabelId` with `InternedAppLabel`. - Changed `AppLabel` to use `Debug` for error messages. - Changed `AppLabel` to use interning. - Changed `define_label`/`derive_label` to use interning. - Replaced `define_boxed_label`/`derive_boxed_label` with `define_label`/`derive_label`. - Changed anonymous set ids to be only unique inside a schedule, not globally. - Made interned label types implement their label trait. ### Removed - Removed `define_boxed_label` and `derive_boxed_label`. ## Migration guide - Replace `BoxedScheduleLabel` and `Box<dyn ScheduleLabel>` with `InternedScheduleLabel` or `Interned<dyn ScheduleLabel>`. - Replace `BoxedSystemSet` and `Box<dyn SystemSet>` with `InternedSystemSet` or `Interned<dyn SystemSet>`. - Replace `AppLabelId` with `InternedAppLabel` or `Interned<dyn AppLabel>`. - Types manually implementing `ScheduleLabel`, `AppLabel` or `SystemSet` need to implement: - `dyn_hash` directly instead of implementing `DynHash` - `as_dyn_eq` - Pass labels to `World::try_schedule_scope`, `World::schedule_scope`, `World::try_run_schedule`. `World::run_schedule`, `Schedules::remove`, `Schedules::remove_entry`, `Schedules::contains`, `Schedules::get` and `Schedules::get_mut` by value instead of by reference. --------- Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com> Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-10-25 21:39:23 +00:00
/// This does not work for unions.
#[proc_macro_derive(AppLabel)]
pub fn derive_app_label(input: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(input as syn::DeriveInput);
let mut trait_path = BevyManifest::default().get_path("bevy_app");
Replace all labels with interned labels (#7762) # Objective First of all, this PR took heavy inspiration from #7760 and #5715. It intends to also fix #5569, but with a slightly different approach. This also fixes #9335 by reexporting `DynEq`. ## Solution The advantage of this API is that we can intern a value without allocating for zero-sized-types and for enum variants that have no fields. This PR does this automatically in the `SystemSet` and `ScheduleLabel` derive macros for unit structs and fieldless enum variants. So this should cover many internal and external use cases of `SystemSet` and `ScheduleLabel`. In these optimal use cases, no memory will be allocated. - The interning returns a `Interned<dyn SystemSet>`, which is just a wrapper around a `&'static dyn SystemSet`. - `Hash` and `Eq` are implemented in terms of the pointer value of the reference, similar to my first approach of anonymous system sets in #7676. - Therefore, `Interned<T>` does not implement `Borrow<T>`, only `Deref`. - The debug output of `Interned<T>` is the same as the interned value. Edit: - `AppLabel` is now also interned and the old `derive_label`/`define_label` macros were replaced with the new interning implementation. - Anonymous set ids are reused for different `Schedule`s, reducing the amount of leaked memory. ### Pros - `InternedSystemSet` and `InternedScheduleLabel` behave very similar to the current `BoxedSystemSet` and `BoxedScheduleLabel`, but can be copied without an allocation. - Many use cases don't allocate at all. - Very fast lookups and comparisons when using `InternedSystemSet` and `InternedScheduleLabel`. - The `intern` module might be usable in other areas. - `Interned{ScheduleLabel, SystemSet, AppLabel}` does implement `{ScheduleLabel, SystemSet, AppLabel}`, increasing ergonomics. ### Cons - Implementors of `SystemSet` and `ScheduleLabel` still need to implement `Hash` and `Eq` (and `Clone`) for it to work. ## Changelog ### Added - Added `intern` module to `bevy_utils`. - Added reexports of `DynEq` to `bevy_ecs` and `bevy_app`. ### Changed - Replaced `BoxedSystemSet` and `BoxedScheduleLabel` with `InternedSystemSet` and `InternedScheduleLabel`. - Replaced `impl AsRef<dyn ScheduleLabel>` with `impl ScheduleLabel`. - Replaced `AppLabelId` with `InternedAppLabel`. - Changed `AppLabel` to use `Debug` for error messages. - Changed `AppLabel` to use interning. - Changed `define_label`/`derive_label` to use interning. - Replaced `define_boxed_label`/`derive_boxed_label` with `define_label`/`derive_label`. - Changed anonymous set ids to be only unique inside a schedule, not globally. - Made interned label types implement their label trait. ### Removed - Removed `define_boxed_label` and `derive_boxed_label`. ## Migration guide - Replace `BoxedScheduleLabel` and `Box<dyn ScheduleLabel>` with `InternedScheduleLabel` or `Interned<dyn ScheduleLabel>`. - Replace `BoxedSystemSet` and `Box<dyn SystemSet>` with `InternedSystemSet` or `Interned<dyn SystemSet>`. - Replace `AppLabelId` with `InternedAppLabel` or `Interned<dyn AppLabel>`. - Types manually implementing `ScheduleLabel`, `AppLabel` or `SystemSet` need to implement: - `dyn_hash` directly instead of implementing `DynHash` - `as_dyn_eq` - Pass labels to `World::try_schedule_scope`, `World::schedule_scope`, `World::try_run_schedule`. `World::run_schedule`, `Schedules::remove`, `Schedules::remove_entry`, `Schedules::contains`, `Schedules::get` and `Schedules::get_mut` by value instead of by reference. --------- Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com> Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-10-25 21:39:23 +00:00
let mut dyn_eq_path = trait_path.clone();
trait_path.segments.push(format_ident!("AppLabel").into());
Replace all labels with interned labels (#7762) # Objective First of all, this PR took heavy inspiration from #7760 and #5715. It intends to also fix #5569, but with a slightly different approach. This also fixes #9335 by reexporting `DynEq`. ## Solution The advantage of this API is that we can intern a value without allocating for zero-sized-types and for enum variants that have no fields. This PR does this automatically in the `SystemSet` and `ScheduleLabel` derive macros for unit structs and fieldless enum variants. So this should cover many internal and external use cases of `SystemSet` and `ScheduleLabel`. In these optimal use cases, no memory will be allocated. - The interning returns a `Interned<dyn SystemSet>`, which is just a wrapper around a `&'static dyn SystemSet`. - `Hash` and `Eq` are implemented in terms of the pointer value of the reference, similar to my first approach of anonymous system sets in #7676. - Therefore, `Interned<T>` does not implement `Borrow<T>`, only `Deref`. - The debug output of `Interned<T>` is the same as the interned value. Edit: - `AppLabel` is now also interned and the old `derive_label`/`define_label` macros were replaced with the new interning implementation. - Anonymous set ids are reused for different `Schedule`s, reducing the amount of leaked memory. ### Pros - `InternedSystemSet` and `InternedScheduleLabel` behave very similar to the current `BoxedSystemSet` and `BoxedScheduleLabel`, but can be copied without an allocation. - Many use cases don't allocate at all. - Very fast lookups and comparisons when using `InternedSystemSet` and `InternedScheduleLabel`. - The `intern` module might be usable in other areas. - `Interned{ScheduleLabel, SystemSet, AppLabel}` does implement `{ScheduleLabel, SystemSet, AppLabel}`, increasing ergonomics. ### Cons - Implementors of `SystemSet` and `ScheduleLabel` still need to implement `Hash` and `Eq` (and `Clone`) for it to work. ## Changelog ### Added - Added `intern` module to `bevy_utils`. - Added reexports of `DynEq` to `bevy_ecs` and `bevy_app`. ### Changed - Replaced `BoxedSystemSet` and `BoxedScheduleLabel` with `InternedSystemSet` and `InternedScheduleLabel`. - Replaced `impl AsRef<dyn ScheduleLabel>` with `impl ScheduleLabel`. - Replaced `AppLabelId` with `InternedAppLabel`. - Changed `AppLabel` to use `Debug` for error messages. - Changed `AppLabel` to use interning. - Changed `define_label`/`derive_label` to use interning. - Replaced `define_boxed_label`/`derive_boxed_label` with `define_label`/`derive_label`. - Changed anonymous set ids to be only unique inside a schedule, not globally. - Made interned label types implement their label trait. ### Removed - Removed `define_boxed_label` and `derive_boxed_label`. ## Migration guide - Replace `BoxedScheduleLabel` and `Box<dyn ScheduleLabel>` with `InternedScheduleLabel` or `Interned<dyn ScheduleLabel>`. - Replace `BoxedSystemSet` and `Box<dyn SystemSet>` with `InternedSystemSet` or `Interned<dyn SystemSet>`. - Replace `AppLabelId` with `InternedAppLabel` or `Interned<dyn AppLabel>`. - Types manually implementing `ScheduleLabel`, `AppLabel` or `SystemSet` need to implement: - `dyn_hash` directly instead of implementing `DynHash` - `as_dyn_eq` - Pass labels to `World::try_schedule_scope`, `World::schedule_scope`, `World::try_run_schedule`. `World::run_schedule`, `Schedules::remove`, `Schedules::remove_entry`, `Schedules::contains`, `Schedules::get` and `Schedules::get_mut` by value instead of by reference. --------- Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com> Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-10-25 21:39:23 +00:00
dyn_eq_path.segments.push(format_ident!("DynEq").into());
derive_label(input, "AppLabel", &trait_path, &dyn_eq_path)
}