-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Merged by Bors] - Add attribute to ignore fields of derived labels #5366
Conversation
#[derive(SystemLabel)] | ||
pub enum GenericLabel<T> { | ||
One, | ||
#[system_label(ignore_fields)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#[system_label(ignore_fields)] | |
#[system_label(ignore)] |
Bikeshedding: I think this is marginally clearer, less verbose and more idiomatic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me, that implies that we're ignoring the entire variant, but we're only ignoring the fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I see 🤔 Yeah I think you're right, but we should make sure to make this clear in the docs.
Weird to think that you could set your enum label to the phantomdata variant...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some nits, but I'm on board with this solution and the underlying code implementation looks correct.
Adding to the 0.8 milestone; I think it's important that we have a migration path here. |
@IceSentry this plus #4957 will have to be added to the migration guide. |
|
||
fn main() { | ||
// Unit labels are always equal. | ||
assert_eq!(UnitLabel.as_label(), UnitLabel.as_label()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tests are critical, but won't be run in CI. I actually think that these should be moved to doc tests on SystemLabel
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, but we can't actually add doctests to label types until #5367
Co-authored-by: François <mockersf@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of this additional complexity around ensuring labels don't have values makes me want to revisit #4957. All of this weirdness could be avoided if we just let labels have normal values, be normal structs, and use the derived Hash/PartialEq impls. I think that would be easier to document / understand for users.
Likewise, the benchmarks used to justify #4957 don't account for enums / longer names in the comparison, which I suspect might paint that impl in a worse light. Given the runtime cost scales with the struct name length, we should be benching real world names / enum lengths like VisibilitySystems::UpdateOrthographicFrusta
, not the unit struct DummyLabel
. And ideally we benchmark more complicated schedules with multiple labels. I'm a bit wary of things being optimized out when code only contains instance of a thing (ex: hashes, comparisons, collections, etc).
Too late to rethink for 0.8 (and i think we should merge this to make migrations smoother), but I think the @bevyengine/ecs-team should give this one last pass for 0.9 to do a final weighing of the pros and cons.
I'm not fully convinced one way or the other (and i do really like the elimination of boxing + removing the need for some trait impls in the api), but this doesn't feel clear cut to me yet.
bors r+ |
# 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. -->
Pull request successfully merged into main. Build succeeded: |
Note that on this branch I've optimized comparisons by storing a "key" (u64) along with the |
Ooh that would definitely close the gap / increase my comfort. I think thats worth pursuing. |
I agree; I like the new PR quite a bit and it alleviates some of my worries. And, obviously, I think that #4341 is a good idea (especially with the autolabelling). |
# Objective I noticed while working on #5366 that the documentation for label types wasn't working correctly. Having experimented with this for a few weeks, I believe that generating docs in macros is more effort than it's worth. ## Solution Add more boilerplate, copy-paste and edit the docs across types. This also lets us add custom doctests for specific types. Also, we don't need `concat_idents` as a dependency anymore.
# Objective Fixes bevyengine#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. -->
# Objective I noticed while working on bevyengine#5366 that the documentation for label types wasn't working correctly. Having experimented with this for a few weeks, I believe that generating docs in macros is more effort than it's worth. ## Solution Add more boilerplate, copy-paste and edit the docs across types. This also lets us add custom doctests for specific types. Also, we don't need `concat_idents` as a dependency anymore.
# Objective Fixes bevyengine#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. -->
# Objective I noticed while working on bevyengine#5366 that the documentation for label types wasn't working correctly. Having experimented with this for a few weeks, I believe that generating docs in macros is more effort than it's worth. ## Solution Add more boilerplate, copy-paste and edit the docs across types. This also lets us add custom doctests for specific types. Also, we don't need `concat_idents` as a dependency anymore.
# Objective Fixes bevyengine#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. -->
# Objective I noticed while working on bevyengine#5366 that the documentation for label types wasn't working correctly. Having experimented with this for a few weeks, I believe that generating docs in macros is more effort than it's worth. ## Solution Add more boilerplate, copy-paste and edit the docs across types. This also lets us add custom doctests for specific types. Also, we don't need `concat_idents` as a dependency anymore.
Objective
Fixes #5362
Solution
Add the attribute
#[label(ignore_fields)]
for*Label
types.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:
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 solutionsPartialEq
andEq
along with the#[derive(Label)]
macros. This is a breaking change as it requires all users to remove these derives from their types.PhantomData
to be used withignore_fields
-- seems needlessly prescriptive.Changelog
ignore_fields
attribute to the derive macros for*Label
types.