-
-
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
bevy_reflect: Type aliases #5830
Conversation
crates/bevy_reflect/bevy_reflect_derive/src/container_attributes.rs
Outdated
Show resolved
Hide resolved
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.
Allow defining deprecated aliases (separate methods or boolean argument?)
Separated method is more clearer, since deprecation isn't done very often.
Add warning to deserialization (should we error on unregistered type?)
IMO it should be an error, not a warning, since the behavior of deserialized object will be compromised.
Add methods to app (which ones? are they worth having?)
Yes, since usually crate devs register events, assets, reflect types and anything they need on Plugin
, so it would be a good idea to keep consistency.
Co-authored-by: Afonso Lage <lage.afonso@gmail.com>
Yeah I think you're right. I'll make them a separate set of methods.
Well, the warning would only be for usages of deprecated aliases. We don't want to error on those as it allows users to migrate across versions. As discussed on Discord, though, I think I will just include the warning and consider making the error a separate PR/issue.
Makes sense. Should all three methods ( |
crates/bevy_reflect/bevy_reflect_derive/src/container_attributes.rs
Outdated
Show resolved
Hide resolved
crates/bevy_reflect/bevy_reflect_derive/src/container_attributes.rs
Outdated
Show resolved
Hide resolved
Regarding the task list:
|
So you're suggesting just not including any warnings when deserializing deprecated aliases? In this PR at least? |
Deprecated ones probably should have a warning, as those are an entirely new feature that this PR is adding, but anything beyond that I don't think is necessary. Like detecting unregistered names. |
…es.rs Co-authored-by: Nathan Ward <43621845+NathanSWard@users.noreply.github.com>
Since there will be cases when the user explicitly would like to override some alias, there is room for those three methods. At beginning I was not fan of I imagine the most common workflow using those methods would be:
Which made me think if we should add the info to use |
…es.rs Co-authored-by: Afonso Lage <lage.afonso@gmail.com>
Ooh yeah that's a good idea! |
Update: I'm currently waiting on #5805 to land so I can base some of the changes around whatever solution ends up there. I also just think we should have stable type names figured out before moving on to things like type aliases.
|
# Objective - Introduce a stable alternative to [`std::any::type_name`](https://doc.rust-lang.org/std/any/fn.type_name.html). - Rewrite of #5805 with heavy inspiration in design. - On the path to #5830. - Part of solving #3327. ## Solution - Add a `TypePath` trait for static stable type path/name information. - Add a `TypePath` derive macro. - Add a `impl_type_path` macro for implementing internal and foreign types in `bevy_reflect`. --- ## Changelog - Added `TypePath` trait. - Added `DynamicTypePath` trait and `get_type_path` method to `Reflect`. - Added a `TypePath` derive macro. - Added a `bevy_reflect::impl_type_path` for implementing `TypePath` on internal and foreign types in `bevy_reflect`. - Changed `bevy_reflect::utility::(Non)GenericTypeInfoCell` to `(Non)GenericTypedCell<T>` which allows us to be generic over both `TypeInfo` and `TypePath`. - `TypePath` is now a supertrait of `Asset`, `Material` and `Material2d`. - `impl_reflect_struct` needs a `#[type_path = "..."]` attribute to be specified. - `impl_reflect_value` needs to either specify path starting with a double colon (`::core::option::Option`) or an `in my_crate::foo` declaration. - Added `bevy_reflect_derive::ReflectTypePath`. - Most uses of `Ident` in `bevy_reflect_derive` changed to use `ReflectTypePath`. ## Migration Guide - Implementors of `Asset`, `Material` and `Material2d` now also need to derive `TypePath`. - Manual implementors of `Reflect` will need to implement the new `get_type_path` method. ## Open Questions - [x] ~This PR currently does not migrate any usages of `std::any::type_name` to use `bevy_reflect::TypePath` to ease the review process. Should it?~ Migration will be left to a follow-up PR. - [ ] This PR adds a lot of `#[derive(TypePath)]` and `T: TypePath` to satisfy new bounds, mostly when deriving `TypeUuid`. Should we make `TypePath` a supertrait of `TypeUuid`? [Should we remove `TypeUuid` in favour of `TypePath`?](https://github.com/bevyengine/bevy/pull/5805/files/2afbd855327c4b68e0a6b6f03118f289988441a4#r961067892)
Backlog cleanup: closing in favour of linked PR #12387, while having no particular opinion on which approach is better! Both can be considered by reviewers. |
Objective
Reflection relies on type names to access type registrations. Unfortunately, these type names can be (1) rather long, (2) unstable between a crate's features/versions, and (3) very programmer-focused.
This can be problematic for serialized formats such as Bevy's scenes. Something as innocuous as performing an internal refactor can result in downstream users needing to update all of their scenes. For example, moving
my_crate::foo::Foo
tomy_crate::Foo
requires updating the type name everywhere it's used.Additionally, it's not always programmers that are dealing with this data. Designers may find it difficult to understand that
my_crate::inventory::utility::BaseContainer<my_crate::inventory::Item, 10>
really just representsPlayerHotbar
. In fact, the programmers may have even shortened this themselves usingtype PlayerHotbar = ...
(not fair!).Ideally there would be a way to refer to types that were shorter, more stable, and non-programmer friendly.
Solution
Add the ability to register aliases for a type.
Aliases are designated using an attribute on the derive macro for
Reflect
:With this, we can now change our scenes from this:
to:
Alternatively, we could have assigned the aliases via the registry:
Generics
Unfortunately, we cannot so easily handle generic types. The reason for this is that a type with generics will monomorphize to many types— so which type gets the alias? Because aliases map to a single type, we cannot specify them via the macro.
This means that registering generic types requires using the registry:
Deprecation Warnings
As users and crates in the ecosystem start to use aliases, they may at some point decide they want to move from one alias to a new one. We can aid user migration by allowing some aliases to be marked as "deprecated". This means that a user can continue to use a deprecated alias as normal; however, it will print a warning to the console letting them know that the alias may be removed entirely in the future.
To specify a deprecated alias:
Note: This works in theory, but due to how the deserializer is setup, we only actually warn when deserializing Value types. This should be more useful when something like #4561 or #5723 lands.
Comparison to #5805
Both this PR and #5805 are very similar. However, they have slightly different goals and actually pair well together.
#5805 is concerned with defining a replacement for
std::any::type_name
. It is supposed to provide a stable and (generally) unique identifier for a given type. There can only be one for a given type.This PR is concerned with defining multiple names that can optionally be used to refer to a type. These names can be overwritten by users and other crates. It gives users more control over how their type can be represented.
In other words, #5805 defines the "one true" type name, while this PR defines "many optional" type names. Or, to use a serde analogy, #5805 is
#[serde(rename)]
, while this PR is#[serde(alias)]
.Task List
Feel free to leave comments regarding the items on this list:
app
(which ones? are they worth having?)Changelog
TODO
Migration Guide
TODO