mirror of
https://github.com/bevyengine/bevy.git
synced 2026-05-06 06:06:42 -04:00
Change the ambiguity_detection test to be more strict. (#23846)
# Objective - Fixes #23843 by preventing these systems from recurring inside Bevy. - Note this does not fix this for users of Bevy. They would need to setup their own "strict" checking. ## Solution - Disable `auto_insert_apply_deferred` in the `ambiguity_detection` example. Now these stages won't accidentally resolve these ambiguities, so they will be detected! - Stop running the app in `ambiguity_detection` and just manually initialize the schedules. - We have to do this otherwise the schedules just panic because they depend on various resource initializations to be executed by commands (which were previously being applied by the automatically inserted `apply_deferred`). ### Caveats: - The ambiguity_detection CI test now won't detect ambiguities in runtime-added systems. - This is not a pattern we use today, and I'd encourage us to **delete** systems instead so that tooling can grab the systems before the app runs. - To clarify, this is **not** ambiguity detection in general - just Bevy's CI test that is affected. ## Testing - Ran the examples and all the ambiguities have been fixed in previous PRs.
This commit is contained in:
@@ -35,17 +35,21 @@ fn main() {
|
|||||||
let sub_app = app.sub_app_mut(bevy_render::RenderApp);
|
let sub_app = app.sub_app_mut(bevy_render::RenderApp);
|
||||||
configure_ambiguity_detection(sub_app);
|
configure_ambiguity_detection(sub_app);
|
||||||
|
|
||||||
|
// Make sure all the system stuff is added.
|
||||||
app.finish();
|
app.finish();
|
||||||
app.cleanup();
|
app.cleanup();
|
||||||
app.update();
|
|
||||||
|
|
||||||
let main_app_ambiguities = count_ambiguities(app.main());
|
let main_app_ambiguities = count_ambiguities(app.main_mut());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
main_app_ambiguities.total(),
|
main_app_ambiguities.total(),
|
||||||
0,
|
0,
|
||||||
"Main app has unexpected ambiguities among the following schedules: \n{main_app_ambiguities:#?}.",
|
"Main app has unexpected ambiguities among the following schedules: \n{main_app_ambiguities:#?}.",
|
||||||
);
|
);
|
||||||
let render_app_ambiguities = count_ambiguities(app.sub_app(bevy_render::RenderApp));
|
|
||||||
|
let render_app = app.sub_app_mut(bevy_render::RenderApp);
|
||||||
|
// Initialize the MainWorld so the render world systems don't fail initialization.
|
||||||
|
render_app.init_resource::<bevy_render::MainWorld>();
|
||||||
|
let render_app_ambiguities = count_ambiguities(render_app);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
render_app_ambiguities.total(),
|
render_app_ambiguities.total(),
|
||||||
0,
|
0,
|
||||||
@@ -69,6 +73,14 @@ fn configure_ambiguity_detection(sub_app: &mut SubApp) {
|
|||||||
schedule.set_build_settings(ScheduleBuildSettings {
|
schedule.set_build_settings(ScheduleBuildSettings {
|
||||||
// NOTE: you can change this to `LogLevel::Ignore` to easily see the current number of ambiguities.
|
// NOTE: you can change this to `LogLevel::Ignore` to easily see the current number of ambiguities.
|
||||||
ambiguity_detection: LogLevel::Warn,
|
ambiguity_detection: LogLevel::Warn,
|
||||||
|
// With auto-inserted apply_deferred stages, these can cause two ambiguous systems to
|
||||||
|
// become accidentally ordered by one of the apply_deferred stages. Disabling requires
|
||||||
|
// us to meet a higher bar. We don't just want no ambiguities - we also don't want
|
||||||
|
// changes to systems or the auto-insert code from "creating" new ambiguities (by
|
||||||
|
// reordering the graph). However, the cost is that the graph is no longer runnable,
|
||||||
|
// since Bevy crates often rely on auto-insert apply_deferred to not panic (e.g.,
|
||||||
|
// because a resource wasn't inserted).
|
||||||
|
auto_insert_apply_deferred: false,
|
||||||
use_shortnames: false,
|
use_shortnames: false,
|
||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
@@ -76,12 +88,23 @@ fn configure_ambiguity_detection(sub_app: &mut SubApp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of conflicting systems per schedule.
|
/// Returns the number of conflicting systems per schedule.
|
||||||
fn count_ambiguities(sub_app: &SubApp) -> AmbiguitiesCount {
|
fn count_ambiguities(sub_app: &mut SubApp) -> AmbiguitiesCount {
|
||||||
let schedules = sub_app.world().resource::<Schedules>();
|
let schedule_labels = sub_app
|
||||||
|
.world()
|
||||||
|
.resource::<Schedules>()
|
||||||
|
.iter()
|
||||||
|
.map(|(_, schedule)| schedule.label())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
let mut ambiguities = <HashMap<_, _>>::default();
|
let mut ambiguities = <HashMap<_, _>>::default();
|
||||||
for (_, schedule) in schedules.iter() {
|
for label in schedule_labels {
|
||||||
let ambiguities_in_schedule = schedule.graph().conflicting_systems().len();
|
let ambiguities_in_schedule =
|
||||||
ambiguities.insert(schedule.label(), ambiguities_in_schedule);
|
sub_app
|
||||||
|
.world_mut()
|
||||||
|
.schedule_scope(label, |world, schedule| {
|
||||||
|
schedule.initialize(world).unwrap().unwrap();
|
||||||
|
schedule.graph().conflicting_systems().len()
|
||||||
|
});
|
||||||
|
ambiguities.insert(label, ambiguities_in_schedule);
|
||||||
}
|
}
|
||||||
AmbiguitiesCount(ambiguities)
|
AmbiguitiesCount(ambiguities)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user