bevy_reflect: Nested TypeInfo getters
#13321
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Objective
Right now,
TypeInfocan be accessed directly from a type using eitherTyped::type_infoorReflect::get_represented_type_info.However, once that
TypeInfois accessed, any nested types must be accessed via theTypeRegistry.Solution
Enable nested types within a
TypeInfoto be retrieved directly.The particular implementation was chosen for two reasons.
Firstly, we can't just store
TypeInfoinside anotherTypeInfodirectly. This is because some types are recursive and would result in a deadlock when trying to create theTypeInfo(i.e. it has to create theTypeInfobefore it can use it, but it also needs theTypeInfobefore it can create it). Therefore, we must instead store the function so it can be retrieved lazily.I had considered also using a
OnceLockor something to lazily cache the info, but I figured we can look into optimizations later. The API should remain the same with or without theOnceLock.Secondly, a new wrapper trait had to be introduced:
MaybeTyped. LikeRegisterForReflection, this trait is#[doc(hidden)]and only exists so that we can properly handle dynamic type fields without requiring them to implementTyped. We don't want dynamic types to implementTypeddue to the fact that it would make the return typeOption<&'static TypeInfo>for all types even though only the dynamic types ever need to returnNone(see #6971 for details).Users should never have to interact with this trait as it has a blanket impl for all
Typedtypes. AndTypedis automatically implemented when derivingReflect(as it is required).The one downside is we do need to return
Option<&'static TypeInfo>from all these new methods so that we can handle the dynamic cases. If we didn't have to, we'd be able to get rid of theOptionentirely. But I think that's an okay tradeoff for this one part of the API, and keeps the other APIs intact.Testing
This PR contains tests to verify everything works as expected. You can test locally by running:
Changelog
Public Changes
ArrayInfo::item_infomethodNamedField::type_infomethodUnnamedField::type_infomethodListInfo::item_infomethodMapInfo::key_infomethodMapInfo::value_infomethodTypedbound (remember that this is automatically satisfied for all types that deriveReflect)Internal Changes
MaybeTypedtraitMigration Guide
All active fields for reflected types (including lists, maps, tuples, etc.), must implement
Typed. For the majority of users this won't have any visible impact.However, users implementing
Reflectmanually may need to update their types to implementTypedif they weren't already.Additionally, custom dynamic types will need to implement the new hidden
MaybeTypedtrait.