From 55402bdf2e10f78833f207b76aec2d1b1ad56b2e Mon Sep 17 00:00:00 2001 From: davier Date: Tue, 12 Dec 2023 20:44:43 +0100 Subject: [PATCH] Fix debug printing for dynamic types (#10740) # Objective Printing `DynamicStruct` with a debug format does not show the contained type anymore. For instance, in `examples/reflection/reflection.rs`, adding `dbg!(&reflect_value);` to line 96 will print: ```rust [examples/reflection/reflection.rs:96] &reflect_value = DynamicStruct(bevy_reflect::DynamicStruct { a: 4, nested: DynamicStruct(bevy_reflect::DynamicStruct { b: 8, }), }) ``` ## Solution Show the represented type instead (`reflection::Foo` and `reflection::Bar` in this case): ```rust [examples/reflection/reflection.rs:96] &reflect_value = DynamicStruct(reflection::Foo { a: 4, nested: DynamicStruct(reflection::Bar { b: 8, }), }) ``` --------- Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com> --- crates/bevy_reflect/src/array.rs | 8 ++- crates/bevy_reflect/src/lib.rs | 67 +++++++++++++++++++++++++ crates/bevy_reflect/src/struct_trait.rs | 7 ++- crates/bevy_reflect/src/tuple_struct.rs | 7 ++- 4 files changed, 86 insertions(+), 3 deletions(-) diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index 760edc3f91..1497aeb149 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -5,7 +5,7 @@ use crate::{ use bevy_reflect_derive::impl_type_path; use std::{ any::{Any, TypeId}, - fmt::Debug, + fmt::{Debug, Formatter}, hash::{Hash, Hasher}, }; @@ -301,6 +301,12 @@ impl Reflect for DynamicArray { fn is_dynamic(&self) -> bool { true } + + fn debug(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "DynamicArray(")?; + array_debug(self, f)?; + write!(f, ")") + } } impl Array for DynamicArray { diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 40778f299f..3eb719b554 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1927,6 +1927,73 @@ bevy_reflect::tests::Test { ); } + #[test] + fn dynamic_types_debug_format() { + #[derive(Debug, Reflect)] + struct TestTupleStruct(u32); + + #[derive(Debug, Reflect)] + enum TestEnum { + A(u32), + B, + } + + #[derive(Debug, Reflect)] + // test DynamicStruct + struct TestStruct { + // test DynamicTuple + tuple: (u32, u32), + // test DynamicTupleStruct + tuple_struct: TestTupleStruct, + // test DynamicList + list: Vec, + // test DynamicArray + array: [u32; 3], + // test DynamicEnum + e: TestEnum, + // test DynamicMap + map: HashMap, + // test reflected value + value: u32, + } + let mut map = HashMap::new(); + map.insert(9, 10); + let mut test_struct = TestStruct { + tuple: (0, 1), + list: vec![2, 3, 4], + array: [5, 6, 7], + tuple_struct: TestTupleStruct(8), + e: TestEnum::A(11), + map, + value: 12, + } + .clone_value(); + let test_struct = test_struct.downcast_mut::().unwrap(); + + // test unknown DynamicStruct + let mut test_unknown_struct = DynamicStruct::default(); + test_unknown_struct.insert("a", 13); + test_struct.insert("unknown_struct", test_unknown_struct); + // test unknown DynamicTupleStruct + let mut test_unknown_tuple_struct = DynamicTupleStruct::default(); + test_unknown_tuple_struct.insert(14); + test_struct.insert("unknown_tuplestruct", test_unknown_tuple_struct); + assert_eq!( + format!("{:?}", test_struct), + "DynamicStruct(bevy_reflect::tests::TestStruct { \ + tuple: DynamicTuple((0, 1)), \ + tuple_struct: DynamicTupleStruct(bevy_reflect::tests::TestTupleStruct(8)), \ + list: DynamicList([2, 3, 4]), \ + array: DynamicArray([5, 6, 7]), \ + e: DynamicEnum(A(11)), \ + map: DynamicMap({9: 10}), \ + value: 12, \ + unknown_struct: DynamicStruct(_ { a: 13 }), \ + unknown_tuplestruct: DynamicTupleStruct(_(14)) \ + })" + ); + } + #[cfg(feature = "glam")] mod glam { use super::*; diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index 512aeae3ec..4f2f25bbd7 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -543,7 +543,12 @@ pub fn struct_partial_eq(a: &S, b: &dyn Reflect) -> Option { /// ``` #[inline] pub fn struct_debug(dyn_struct: &dyn Struct, f: &mut Formatter<'_>) -> std::fmt::Result { - let mut debug = f.debug_struct(dyn_struct.reflect_type_path()); + let mut debug = f.debug_struct( + dyn_struct + .get_represented_type_info() + .map(|s| s.type_path()) + .unwrap_or("_"), + ); for field_index in 0..dyn_struct.field_len() { let field = dyn_struct.field_at(field_index).unwrap(); debug.field( diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index c2e66eafff..f0c453575b 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -453,7 +453,12 @@ pub fn tuple_struct_debug( dyn_tuple_struct: &dyn TupleStruct, f: &mut Formatter<'_>, ) -> std::fmt::Result { - let mut debug = f.debug_tuple(dyn_tuple_struct.reflect_type_path()); + let mut debug = f.debug_tuple( + dyn_tuple_struct + .get_represented_type_info() + .map(|s| s.type_path()) + .unwrap_or("_"), + ); for field in dyn_tuple_struct.iter_fields() { debug.field(&field as &dyn Debug); }