pub trait A {}
// zero or more B for each A
pub trait B {
// exactly one A for each B
type MyA: A;
}
// private indirection to allow trait queries on traits with associated types.
#[bevy_trait_query::queryable]
trait BQueryable<TA: A>: B<MyA = TA> {}
impl<TA: A, U: B<MyA = TA>> BQueryable<TA> for U {}
pub struct APlugin<TA: A>(PhantomData<TA>);
fn get_all_b<TA: A>(query: Query<&dyn BQueryable<TA>>) {
for bees in query.iter() {
for b in bees.iter() {
// do something with B
}
}
}
impl<TA: A + Component> Plugin for APlugin<TA> {
fn build(&self, app: &mut App) {
app.add_system(get_all_b::<TA>);
}
}
pub struct BPlugin<TB: B>(PhantomData<TB>);
impl<TA: A, TB: B<MyA = TA> + Component> Plugin for BPlugin<TB> {
fn build(&self, app: &mut App) {
app.register_component_as::<dyn BQueryable<TA>, TB>();
}
}
But since there may be zero BPlugins for an APlugin, when the system is initialized added and the registry is supposed to be sealed, there is no available registry because no components were registered for dyn BQueryable<TA> where TA == A in APlugin and the app panics.
Since TraitImplRegistry is private and that is relied upon for safety, inserted an empty TraitImplRegistry is not an option.
The only only current workaround (AFAIK) is to change the implementation of Plugin for APlugin to
fn build(&self, app: &mut App) {
#[derive(Component)]
struct TraitQueryWorkaround<UA: A>(PhantomData<UA>);
impl<UA: A> B for TraitQueryWorkaround<UA> {
type MyA = UA;
}
app.register_component_as::<dyn BQueryable<TA>, TraitQueryWorkaround<UA>>();
app.add_system(get_all_b::<TA>);
}
which inserts a private, useless component into the registry which is not ideal.
Changes
This PR simply changes the panic to a warning and inserts an empty TraitImplRegistry just before sealing.
Why?
The problem that I'm running into is this:
But since there may be zero
BPlugins
for anAPlugin
, when the system is initialized added and the registry is supposed to be sealed, there is no available registry because no components were registered fordyn BQueryable<TA>
whereTA == A in APlugin
and the app panics.Since
TraitImplRegistry
is private and that is relied upon for safety, inserted an emptyTraitImplRegistry
is not an option.The only only current workaround (AFAIK) is to change the implementation of
Plugin
forAPlugin
towhich inserts a private, useless component into the registry which is not ideal.
Changes
This PR simply changes the panic to a warning and inserts an empty
TraitImplRegistry
just before sealing.