Auto merge of #66716 - derekdreery:debug_non_exhaustive, r=dtolnay
Implement `DebugStruct::non_exhaustive`. This patch adds a function (finish_non_exhaustive) to add ellipsis before the closing brace when formatting using `DebugStruct`. ## Example ```rust #![feature(debug_non_exhaustive)] use std::fmt; struct Bar { bar: i32, hidden: f32, } impl fmt::Debug for Bar { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("Bar") .field("bar", &self.bar) .non_exhaustive(true) // Show that some other field(s) exist. .finish() } } assert_eq!( format!("{:?}", Bar { bar: 10, hidden: 1.0 }), "Bar { bar: 10, .. }", ); ```
This commit is contained in:
commit
8cacf50563
3 changed files with 142 additions and 0 deletions
|
@ -159,6 +159,62 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Marks the struct as non-exhaustive, indicating to the reader that there are some other
|
||||
/// fields that are not shown in the debug representation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(debug_non_exhaustive)]
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Bar {
|
||||
/// bar: i32,
|
||||
/// hidden: f32,
|
||||
/// }
|
||||
///
|
||||
/// impl fmt::Debug for Bar {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_struct("Bar")
|
||||
/// .field("bar", &self.bar)
|
||||
/// .finish_non_exhaustive() // Show that some other field(s) exist.
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Bar { bar: 10, hidden: 1.0 }),
|
||||
/// "Bar { bar: 10, .. }",
|
||||
/// );
|
||||
/// ```
|
||||
#[unstable(feature = "debug_non_exhaustive", issue = "67364")]
|
||||
pub fn finish_non_exhaustive(&mut self) -> fmt::Result {
|
||||
self.result = self.result.and_then(|_| {
|
||||
// Draw non-exhaustive dots (`..`), and open brace if necessary (no fields).
|
||||
if self.is_pretty() {
|
||||
if !self.has_fields {
|
||||
self.fmt.write_str(" {\n")?;
|
||||
}
|
||||
let mut slot = None;
|
||||
let mut state = Default::default();
|
||||
let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut state);
|
||||
writer.write_str("..\n")?;
|
||||
} else {
|
||||
if self.has_fields {
|
||||
self.fmt.write_str(", ..")?;
|
||||
} else {
|
||||
self.fmt.write_str(" { ..")?;
|
||||
}
|
||||
}
|
||||
if self.is_pretty() {
|
||||
self.fmt.write_str("}")?
|
||||
} else {
|
||||
self.fmt.write_str(" }")?;
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
self.result
|
||||
}
|
||||
|
||||
/// Finishes output and returns any error encountered.
|
||||
///
|
||||
/// # Examples
|
||||
|
|
|
@ -89,6 +89,91 @@ mod debug_struct {
|
|||
baz: 10/20,
|
||||
},
|
||||
hello: \"world\",
|
||||
}",
|
||||
format!("{:#?}", Bar)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_only_non_exhaustive() {
|
||||
struct Foo;
|
||||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("Foo").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("Foo { .. }", format!("{:?}", Foo));
|
||||
assert_eq!(
|
||||
"Foo {
|
||||
..
|
||||
}",
|
||||
format!("{:#?}", Foo)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiple_and_non_exhaustive() {
|
||||
struct Foo;
|
||||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("Foo")
|
||||
.field("bar", &true)
|
||||
.field("baz", &format_args!("{}/{}", 10, 20))
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("Foo { bar: true, baz: 10/20, .. }", format!("{:?}", Foo));
|
||||
assert_eq!(
|
||||
"Foo {
|
||||
bar: true,
|
||||
baz: 10/20,
|
||||
..
|
||||
}",
|
||||
format!("{:#?}", Foo)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nested_non_exhaustive() {
|
||||
struct Foo;
|
||||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("Foo")
|
||||
.field("bar", &true)
|
||||
.field("baz", &format_args!("{}/{}", 10, 20))
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
struct Bar;
|
||||
|
||||
impl fmt::Debug for Bar {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("Bar")
|
||||
.field("foo", &Foo)
|
||||
.field("hello", &"world")
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
"Bar { foo: Foo { bar: true, baz: 10/20, .. }, hello: \"world\", .. }",
|
||||
format!("{:?}", Bar)
|
||||
);
|
||||
assert_eq!(
|
||||
"Bar {
|
||||
foo: Foo {
|
||||
bar: true,
|
||||
baz: 10/20,
|
||||
..
|
||||
},
|
||||
hello: \"world\",
|
||||
..
|
||||
}",
|
||||
format!("{:#?}", Bar)
|
||||
);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#![feature(core_private_bignum)]
|
||||
#![feature(core_private_diy_float)]
|
||||
#![feature(debug_map_key_value)]
|
||||
#![feature(debug_non_exhaustive)]
|
||||
#![feature(dec2flt)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
#![feature(fixed_size_array)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue