Skip to content

Commit 89b417c

Browse files
committed
Adding Debug implementations for App, Stage, Schedule, Query, QueryState, etc. (#6214)
# Objective - Adding Debug implementations for App, Stage, Schedule, Query, QueryState. - Fixes #1130. ## Solution - Implemented std::fmt::Debug for a number of structures. --- ## Changelog Also added Debug implementations for ParallelSystemExecutor, SingleThreadedExecutor, various RunCriteria structures, SystemContainer, and SystemDescriptor. Opinions are sure to differ as to what information to provide in a Debug implementation. Best guess was taken for this initial version for these structures. Co-authored-by: targrub <62773321+targrub@users.noreply.github.com>
1 parent 55d126c commit 89b417c

File tree

10 files changed

+201
-5
lines changed

10 files changed

+201
-5
lines changed

crates/bevy_app/src/app.rs

+20
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,32 @@ pub struct App {
7070
sub_apps: HashMap<AppLabelId, SubApp>,
7171
}
7272

73+
impl Debug for App {
74+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75+
write!(f, "App {{ sub_apps: ")?;
76+
f.debug_map()
77+
.entries(self.sub_apps.iter().map(|(k, v)| (k, v)))
78+
.finish()?;
79+
write!(f, "}}")
80+
}
81+
}
82+
7383
/// Each `SubApp` has its own [`Schedule`] and [`World`], enabling a separation of concerns.
7484
struct SubApp {
7585
app: App,
7686
runner: Box<dyn Fn(&mut World, &mut App)>,
7787
}
7888

89+
impl Debug for SubApp {
90+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91+
write!(f, "SubApp {{ app: ")?;
92+
f.debug_map()
93+
.entries(self.app.sub_apps.iter().map(|(k, v)| (k, v)))
94+
.finish()?;
95+
write!(f, "}}")
96+
}
97+
}
98+
7999
impl Default for App {
80100
fn default() -> Self {
81101
let mut app = App::empty();

crates/bevy_ecs/src/query/state.rs

+11
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,17 @@ pub struct QueryState<Q: WorldQuery, F: ReadOnlyWorldQuery = ()> {
3535
pub(crate) filter_state: F::State,
3636
}
3737

38+
impl<Q: WorldQuery, F: ReadOnlyWorldQuery> std::fmt::Debug for QueryState<Q, F> {
39+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40+
write!(
41+
f,
42+
"QueryState<Q, F> matched_table_ids: {} matched_archetype_ids: {}",
43+
self.matched_table_ids.len(),
44+
self.matched_archetype_ids.len()
45+
)
46+
}
47+
}
48+
3849
impl<Q: WorldQuery, F: ReadOnlyWorldQuery> FromWorld for QueryState<Q, F> {
3950
fn from_world(world: &mut World) -> Self {
4051
world.query_filtered()

crates/bevy_ecs/src/schedule/executor.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::{schedule::SystemContainer, world::World};
2+
use core::fmt::Debug;
23
use downcast_rs::{impl_downcast, Downcast};
34

45
pub trait ParallelSystemExecutor: Downcast + Send + Sync {
@@ -8,9 +9,15 @@ pub trait ParallelSystemExecutor: Downcast + Send + Sync {
89
fn run_systems(&mut self, systems: &mut [SystemContainer], world: &mut World);
910
}
1011

12+
impl Debug for dyn ParallelSystemExecutor {
13+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14+
write!(f, "dyn ParallelSystemExecutor")
15+
}
16+
}
17+
1118
impl_downcast!(ParallelSystemExecutor);
1219

13-
#[derive(Default)]
20+
#[derive(Debug, Default)]
1421
pub struct SingleThreadedExecutor;
1522

1623
impl ParallelSystemExecutor for SingleThreadedExecutor {

crates/bevy_ecs/src/schedule/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use bevy_utils::HashMap;
3737
/// In this way, the properties of the child schedule can be set differently from the parent.
3838
/// For example, it can be set to run only once during app execution, while the parent schedule
3939
/// runs indefinitely.
40-
#[derive(Default)]
40+
#[derive(Debug, Default)]
4141
pub struct Schedule {
4242
stages: HashMap<StageLabelId, Box<dyn Stage>>,
4343
stage_order: Vec<StageLabelId>,

crates/bevy_ecs/src/schedule/run_criteria.rs

+56-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
use crate::{
2+
prelude::System,
23
schedule::{GraphNode, RunCriteriaLabel, RunCriteriaLabelId},
34
system::{BoxedSystem, IntoSystem, Local},
45
world::World,
56
};
7+
use core::fmt::Debug;
68
use std::borrow::Cow;
79

810
/// Determines whether a system should be executed or not, and how many times it should be ran each
@@ -66,7 +68,7 @@ impl From<bool> for ShouldRun {
6668
}
6769
}
6870

69-
#[derive(Default)]
71+
#[derive(Debug, Default)]
7072
pub(crate) struct BoxedRunCriteria {
7173
criteria_system: Option<BoxedSystem<(), ShouldRun>>,
7274
initialized: bool,
@@ -93,6 +95,7 @@ impl BoxedRunCriteria {
9395
}
9496
}
9597

98+
#[derive(Debug)]
9699
pub(crate) enum RunCriteriaInner {
97100
Single(BoxedSystem<(), ShouldRun>),
98101
Piped {
@@ -101,6 +104,7 @@ pub(crate) enum RunCriteriaInner {
101104
},
102105
}
103106

107+
#[derive(Debug)]
104108
pub(crate) struct RunCriteriaContainer {
105109
pub(crate) should_run: ShouldRun,
106110
pub(crate) inner: RunCriteriaInner,
@@ -165,17 +169,19 @@ impl GraphNode for RunCriteriaContainer {
165169
}
166170
}
167171

172+
#[derive(Debug)]
168173
pub enum RunCriteriaDescriptorOrLabel {
169174
Descriptor(RunCriteriaDescriptor),
170175
Label(RunCriteriaLabelId),
171176
}
172177

173-
#[derive(Clone, Copy)]
178+
#[derive(Debug, Clone, Copy)]
174179
pub(crate) enum DuplicateLabelStrategy {
175180
Panic,
176181
Discard,
177182
}
178183

184+
#[derive(Debug)]
179185
pub struct RunCriteriaDescriptor {
180186
pub(crate) system: RunCriteriaSystem,
181187
pub(crate) label: Option<RunCriteriaLabelId>,
@@ -184,6 +190,7 @@ pub struct RunCriteriaDescriptor {
184190
pub(crate) after: Vec<RunCriteriaLabelId>,
185191
}
186192

193+
#[derive(Debug)]
187194
pub(crate) enum RunCriteriaSystem {
188195
Single(BoxedSystem<(), ShouldRun>),
189196
Piped(BoxedSystem<ShouldRun, ShouldRun>),
@@ -326,6 +333,7 @@ where
326333
}
327334
}
328335

336+
#[derive(Debug)]
329337
pub struct RunCriteria {
330338
label: RunCriteriaLabelId,
331339
}
@@ -346,3 +354,49 @@ impl RunCriteria {
346354
}
347355
}
348356
}
357+
358+
impl Debug for dyn System<In = (), Out = ShouldRun> + 'static {
359+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
360+
write!(
361+
f,
362+
"System {} with In=(), Out=ShouldRun: {{{}}}",
363+
self.name(),
364+
{
365+
if self.is_send() {
366+
if self.is_exclusive() {
367+
"is_send is_exclusive"
368+
} else {
369+
"is_send"
370+
}
371+
} else if self.is_exclusive() {
372+
"is_exclusive"
373+
} else {
374+
""
375+
}
376+
},
377+
)
378+
}
379+
}
380+
381+
impl Debug for dyn System<In = ShouldRun, Out = ShouldRun> + 'static {
382+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
383+
write!(
384+
f,
385+
"System {} with In=ShouldRun, Out=ShouldRun: {{{}}}",
386+
self.name(),
387+
{
388+
if self.is_send() {
389+
if self.is_exclusive() {
390+
"is_send is_exclusive"
391+
} else {
392+
"is_send"
393+
}
394+
} else if self.is_exclusive() {
395+
"is_exclusive"
396+
} else {
397+
""
398+
}
399+
},
400+
)
401+
}
402+
}

crates/bevy_ecs/src/schedule/stage.rs

+72-1
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ use crate::{
1414
};
1515
use bevy_ecs_macros::Resource;
1616
use bevy_utils::{tracing::warn, HashMap, HashSet};
17+
use core::fmt::Debug;
1718
use downcast_rs::{impl_downcast, Downcast};
1819

19-
use super::IntoSystemDescriptor;
20+
use super::{IntoSystemDescriptor, Schedule};
2021

2122
/// A type that can run as a step of a [`Schedule`](super::Schedule).
2223
pub trait Stage: Downcast + Send + Sync {
@@ -25,6 +26,18 @@ pub trait Stage: Downcast + Send + Sync {
2526
fn run(&mut self, world: &mut World);
2627
}
2728

29+
impl Debug for dyn Stage {
30+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31+
if let Some(as_systemstage) = self.as_any().downcast_ref::<SystemStage>() {
32+
write!(f, "{:?}", as_systemstage)
33+
} else if let Some(as_schedule) = self.as_any().downcast_ref::<Schedule>() {
34+
write!(f, "{:?}", as_schedule)
35+
} else {
36+
write!(f, "Unknown dyn Stage")
37+
}
38+
}
39+
}
40+
2841
impl_downcast!(Stage);
2942

3043
/// When this resource is present in the `App`'s `Resources`,
@@ -584,6 +597,64 @@ impl SystemStage {
584597
}
585598
Ok(labels)
586599
}
600+
601+
pub fn vec_system_container_debug(
602+
&self,
603+
name: &str,
604+
v: &Vec<SystemContainer>,
605+
f: &mut std::fmt::Formatter<'_>,
606+
) -> std::fmt::Result {
607+
write!(f, "{}: ", name)?;
608+
if v.len() > 1 {
609+
writeln!(f, "[")?;
610+
for sc in v.iter() {
611+
writeln!(f, "{:?},", sc)?;
612+
}
613+
write!(f, "], ")
614+
} else {
615+
write!(f, "{:?}, ", v)
616+
}
617+
}
618+
}
619+
620+
impl std::fmt::Debug for SystemStage {
621+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
622+
write!(f, "SystemStage: {{ ")?;
623+
write!(
624+
f,
625+
"world_id: {:?}, executor: {:?}, stage_run_criteria: {:?}, run_criteria: {:?}, ",
626+
self.world_id, self.executor, self.stage_run_criteria, self.run_criteria
627+
)?;
628+
self.vec_system_container_debug("exclusive_at_start", &self.exclusive_at_start, f)?;
629+
self.vec_system_container_debug(
630+
"exclusive_before_commands",
631+
&self.exclusive_before_commands,
632+
f,
633+
)?;
634+
self.vec_system_container_debug("exclusive_at_end", &self.exclusive_at_end, f)?;
635+
self.vec_system_container_debug("parallel", &self.parallel, f)?;
636+
write!(
637+
f,
638+
"systems_modified: {:?}, uninitialized_run_criteria: {:?}, ",
639+
self.systems_modified, self.uninitialized_run_criteria
640+
)?;
641+
write!(
642+
f,
643+
"uninitialized_at_start: {:?}, uninitialized_before_commands: {:?}, ",
644+
self.uninitialized_at_start, self.uninitialized_before_commands
645+
)?;
646+
write!(
647+
f,
648+
"uninitialized_at_end: {:?}, uninitialized_parallel: {:?}, ",
649+
self.uninitialized_at_end, self.uninitialized_parallel
650+
)?;
651+
write!(
652+
f,
653+
"last_tick_check: {:?}, apply_buffers: {:?}, ",
654+
self.last_tick_check, self.apply_buffers
655+
)?;
656+
write!(f, "must_read_resource: {:?}}}", self.must_read_resource)
657+
}
587658
}
588659

589660
/// Sorts given system containers topologically, populates their resolved dependencies

crates/bevy_ecs/src/schedule/system_container.rs

+7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::{
66
},
77
system::System,
88
};
9+
use core::fmt::Debug;
910
use std::borrow::Cow;
1011

1112
pub struct SystemContainer {
@@ -83,6 +84,12 @@ impl SystemContainer {
8384
}
8485
}
8586

87+
impl Debug for SystemContainer {
88+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89+
write!(f, "{{{:?}}}", &self.system())
90+
}
91+
}
92+
8693
impl GraphNode for SystemContainer {
8794
type Label = SystemLabelId;
8895

crates/bevy_ecs/src/schedule/system_descriptor.rs

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ pub(crate) enum AmbiguityDetection {
4141
/// .with_system(do_the_other_thing.after(Something))
4242
/// .with_system(do_something_else.at_end());
4343
/// ```
44+
#[derive(Debug)]
4445
pub struct SystemDescriptor {
4546
pub(crate) system: BoxedSystem<(), ()>,
4647
pub(crate) exclusive_insertion_point: Option<ExclusiveInsertionPoint>,

crates/bevy_ecs/src/system/query.rs

+6
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,12 @@ pub struct Query<'world, 'state, Q: WorldQuery, F: ReadOnlyWorldQuery = ()> {
280280
pub(crate) change_tick: u32,
281281
}
282282

283+
impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> std::fmt::Debug for Query<'w, 's, Q, F> {
284+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
285+
write!(f, "Query {{ matched entities: {}, world: {:?}, state: {:?}, last_change_tick: {}, change_tick: {} }}", self.iter().count(), self.world, self.state, self.last_change_tick, self.change_tick)
286+
}
287+
}
288+
283289
impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> Query<'w, 's, Q, F> {
284290
/// Creates a new query.
285291
///

crates/bevy_ecs/src/system/system.rs

+19
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use bevy_utils::tracing::warn;
2+
use core::fmt::Debug;
23

34
use crate::{
45
archetype::ArchetypeComponentId, change_detection::MAX_CHANGE_AGE, component::ComponentId,
@@ -95,3 +96,21 @@ pub(crate) fn check_system_change_tick(
9596
*last_change_tick = change_tick.wrapping_sub(MAX_CHANGE_AGE);
9697
}
9798
}
99+
100+
impl Debug for dyn System<In = (), Out = ()> {
101+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102+
write!(f, "System {}: {{{}}}", self.name(), {
103+
if self.is_send() {
104+
if self.is_exclusive() {
105+
"is_send is_exclusive"
106+
} else {
107+
"is_send"
108+
}
109+
} else if self.is_exclusive() {
110+
"is_exclusive"
111+
} else {
112+
""
113+
}
114+
},)
115+
}
116+
}

0 commit comments

Comments
 (0)