Currently, the #[require(...)] attribute internally registers component requirements using register_required_components_manual. This is done recursively in a way where every requirement in the "inheritance tree" is added into a flat RequiredComponents hash map with component constructors and inheritance depths stored.
However, this does not consider runtime requirements: if a plugin has already registered C as required by B, and a component A requires B through the macro attribute, spawning an entity with A won't add C. The required_by hash set for C doesn't have A, and the RequiredComponents of A don't have C.
Intuitively, I would've thought that the macro attribute's requirements were always added before runtime requirements, and in that case I believe this shouldn't have been an issue. But the macro requirements are based on Component::register_required_components, which in a lot of cases (I think) is only called after the first time a bundle with the component is inserted. So if a runtime requirement is defined before this (as is often the case, during Plugin::build), the macro may not take it into account.
Solution
Register requirements inherited from the required component in register_required_components_manual_unchecked.
Testing
I added a test, essentially the same as in #16406, and it now passes. I also ran some of the tests in #16409, and they seem to work as expected. All the existing tests for required components pass.
Objective
Fixes #16406.
Currently, the
#[require(...)]
attribute internally registers component requirements usingregister_required_components_manual
. This is done recursively in a way where every requirement in the "inheritance tree" is added into a flatRequiredComponents
hash map with component constructors and inheritance depths stored.However, this does not consider runtime requirements: if a plugin has already registered
C
as required byB
, and a componentA
requiresB
through the macro attribute, spawning an entity withA
won't addC
. Therequired_by
hash set forC
doesn't haveA
, and theRequiredComponents
ofA
don't haveC
.Intuitively, I would've thought that the macro attribute's requirements were always added before runtime requirements, and in that case I believe this shouldn't have been an issue. But the macro requirements are based on
Component::register_required_components
, which in a lot of cases (I think) is only called after the first time a bundle with the component is inserted. So if a runtime requirement is defined before this (as is often the case, duringPlugin::build
), the macro may not take it into account.Solution
Register requirements inherited from the
required
component inregister_required_components_manual_unchecked
.Testing
I added a test, essentially the same as in #16406, and it now passes. I also ran some of the tests in #16409, and they seem to work as expected. All the existing tests for required components pass.