diff options
| author | bors <bors@rust-lang.org> | 2020-01-17 00:20:48 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-01-17 00:20:48 +0000 |
| commit | 8cacf50563ba0f60855d3465f019290d29495ec1 (patch) | |
| tree | 9efd2b59f04a6da177d33545676bd1d346a5e83b | |
| parent | ecbc222855c890c3aabe4848e8d8b312debcf0ff (diff) | |
| parent | 73124df6eba9d81affb3ef597fdaeb4fce82f7af (diff) | |
| download | rust-8cacf50563ba0f60855d3465f019290d29495ec1.tar.gz rust-8cacf50563ba0f60855d3465f019290d29495ec1.zip | |
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, .. }",
);
```
| -rw-r--r-- | src/libcore/fmt/builders.rs | 56 | ||||
| -rw-r--r-- | src/libcore/tests/fmt/builders.rs | 85 | ||||
| -rw-r--r-- | src/libcore/tests/lib.rs | 1 |
3 files changed, 142 insertions, 0 deletions
diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index 626eb1e862d..dd0f3ccb158 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -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 diff --git a/src/libcore/tests/fmt/builders.rs b/src/libcore/tests/fmt/builders.rs index 90a9bccda15..129c121e8ce 100644 --- a/src/libcore/tests/fmt/builders.rs +++ b/src/libcore/tests/fmt/builders.rs @@ -93,6 +93,91 @@ mod debug_struct { 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) + ); + } } mod debug_tuple { diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 86cf6fc104c..8c034938c2b 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -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)] |
