Skip to content

RequiredComponent.inheritance_depth docs do not matchComponent derive impl #19863

Open
@urben1680

Description

@urben1680

Bevy version

main

What you did

I put this in a unit test on lib.rs of bevy_ecs to let me print the required components of A and their depth:

#[derive(Component, Default)]
#[require(B)]
struct A;

#[derive(Component, Default)]
#[require(C)]
struct B;

#[derive(Component, Default)]
#[require(D)]
struct C;

#[derive(Component, Default)]
struct D;

let mut world = World::new();

let a_id = world.register_component::<A>();
std::println!("A: {:?}", a_id);
std::println!("B: {:?}", world.register_component::<B>());
std::println!("C: {:?}", world.register_component::<C>());
std::println!("D: {:?}", world.register_component::<D>());

let required = world
    .components()
    .get_info(a_id)
    .unwrap()
    .required_components();

for (id, meta) in &required.0 {
    std::println!("required id: {id:?}, inheritance_depth: {}", meta.inheritance_depth);
}

What went wrong

This prints:

A: ComponentId(7)
B: ComponentId(8)
C: ComponentId(9)
D: ComponentId(10)
required id: ComponentId(9), inheritance_depth: 1
required id: ComponentId(10), inheritance_depth: 1
required id: ComponentId(8), inheritance_depth: 0

According to the docs of inheritance_depth (I made the significant part bold) ...

The depth of the component requirement in the requirement hierarchy for this component.
This is used for determining which constructor is used in cases where there are duplicate requires.

For example, consider the inheritance tree X -> Y -> Z, where -> indicates a requirement.
X -> Y and Y -> Z are direct requirements with a depth of 0, while Z is only indirectly
required for X with a depth of 1.

In cases where there are multiple conflicting requirements with the same depth, a higher priority
will be given to components listed earlier in the require attribute, or to the latest added requirement
if registered at runtime.

... I expect the inheritance_depth of D: ComponentId(10) to be 2, not 1.

Either the docs are wrong or the implementation?

Right now it seems this can and will cause bugs with required components.

Additional information

I stumbled on this while fixing bundles becoming outdated by World::register_required_component. I also saw for example the issue #16406 required three PRs (plus two closed ones) to be fixed. I can imagine this was caused by the actual issue not being found originally?.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-BugAn unexpected or incorrect behaviorS-Needs-TriageThis issue needs to be labelled

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions