The required components documentation describes the algorithm for resolving multiple constructors for the same component in a required components tree as follows:
In general, this shouldn’t happen often, but when it does the algorithm is simple and predictable:
Use all of the constructors (including default constructors) directly defined in the spawned component’s require list
In the order the requires are defined in #[require()], recursively visit the require list of each of the components in the list (this is a Depth First Search). When a constructor is found, it will only be used if one has not already been found.
However, this is not what actually happens. For example, consider this case:
Now suppose we spawn A. Following the steps described in the docs to determine which constructor will be used for D:
The "spawned component" is A, which does not have a constructor for D, so go to step 2.
A DFS will visit the components in the order A B C D(2) D(1). So when D(2) is visited, it will be used because D hasn't been found yet; and when D(1) is visited, it will not be used because D has been found already.
This suggests that D(2) will be used as the constructor. But that's incorrect: D(1) is actually used.
@cart, do we prefer the implemented behavior or the documented behavior? I think the implemented behavior is better: more locally defined is more likely to be relevant.
The required components documentation describes the algorithm for resolving multiple constructors for the same component in a required components tree as follows:
However, this is not what actually happens. For example, consider this case:
Now suppose we spawn
A
. Following the steps described in the docs to determine which constructor will be used forD
:A
, which does not have a constructor forD
, so go to step 2.A B C D(2) D(1)
. So whenD(2)
is visited, it will be used becauseD
hasn't been found yet; and whenD(1)
is visited, it will not be used becauseD
has been found already.This suggests that
D(2)
will be used as the constructor. But that's incorrect:D(1)
is actually used.