Fix Plugin::build detection (#8103)

This commit is contained in:
Edgar Geier 2023-03-17 01:16:20 +01:00 committed by GitHub
parent f3d6c2d90b
commit 67afd21702
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -12,7 +12,10 @@ use bevy_ecs::{
}, },
}; };
use bevy_utils::{tracing::debug, HashMap, HashSet}; use bevy_utils::{tracing::debug, HashMap, HashSet};
use std::fmt::Debug; use std::{
fmt::Debug,
panic::{catch_unwind, resume_unwind, AssertUnwindSafe},
};
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
use bevy_utils::tracing::info_span; use bevy_utils::tracing::info_span;
@ -80,8 +83,8 @@ pub struct App {
sub_apps: HashMap<AppLabelId, SubApp>, sub_apps: HashMap<AppLabelId, SubApp>,
plugin_registry: Vec<Box<dyn Plugin>>, plugin_registry: Vec<Box<dyn Plugin>>,
plugin_name_added: HashSet<String>, plugin_name_added: HashSet<String>,
/// A private marker to prevent incorrect calls to `App::run()` from `Plugin::build()` /// A private counter to prevent incorrect calls to `App::run()` from `Plugin::build()`
is_building_plugin: bool, building_plugin_depth: usize,
} }
impl Debug for App { impl Debug for App {
@ -228,7 +231,7 @@ impl App {
plugin_name_added: Default::default(), plugin_name_added: Default::default(),
default_schedule_label: Box::new(CoreSchedule::Main), default_schedule_label: Box::new(CoreSchedule::Main),
outer_schedule_label: Box::new(CoreSchedule::Outer), outer_schedule_label: Box::new(CoreSchedule::Outer),
is_building_plugin: false, building_plugin_depth: 0,
} }
} }
@ -291,8 +294,8 @@ impl App {
let _bevy_app_run_span = info_span!("bevy_app").entered(); let _bevy_app_run_span = info_span!("bevy_app").entered();
let mut app = std::mem::replace(self, App::empty()); let mut app = std::mem::replace(self, App::empty());
if app.is_building_plugin { if app.building_plugin_depth > 0 {
panic!("App::run() was called from within Plugin::Build(), which is not allowed."); panic!("App::run() was called from within Plugin::build(), which is not allowed.");
} }
Self::setup(&mut app); Self::setup(&mut app);
@ -765,9 +768,12 @@ impl App {
plugin_name: plugin.name().to_string(), plugin_name: plugin.name().to_string(),
})?; })?;
} }
self.is_building_plugin = true; self.building_plugin_depth += 1;
plugin.build(self); let result = catch_unwind(AssertUnwindSafe(|| plugin.build(self)));
self.is_building_plugin = false; self.building_plugin_depth -= 1;
if let Err(payload) = result {
resume_unwind(payload);
}
self.plugin_registry.push(plugin); self.plugin_registry.push(plugin);
Ok(self) Ok(self)
} }
@ -1071,9 +1077,13 @@ mod tests {
#[should_panic] #[should_panic]
fn cant_call_app_run_from_plugin_build() { fn cant_call_app_run_from_plugin_build() {
struct PluginRun; struct PluginRun;
struct InnerPlugin;
impl Plugin for InnerPlugin {
fn build(&self, _: &mut crate::App) {}
}
impl Plugin for PluginRun { impl Plugin for PluginRun {
fn build(&self, app: &mut crate::App) { fn build(&self, app: &mut crate::App) {
app.run(); app.add_plugin(InnerPlugin).run();
} }
} }
App::new().add_plugin(PluginRun); App::new().add_plugin(PluginRun);