Implement debug_more_non_exhaustive
Add a `.finish_non_exhaustive()` method to `DebugTuple`, `DebugSet`, `DebugList`, and `DebugMap`. This indicates that the structures have remaining items with `..`. This implements the ACP at <https://github.com/rust-lang/libs-team/issues/248>.
This commit is contained in:
parent
68fb25e2eb
commit
827970ebe9
@ -360,6 +360,51 @@ pub fn field_with<F>(&mut self, value_fmt: F) -> &mut Self
|
||||
self
|
||||
}
|
||||
|
||||
/// Marks the tuple 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_more_non_exhaustive)]
|
||||
///
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(i32, String);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_tuple("Foo")
|
||||
/// .field(&self.0)
|
||||
/// .finish_non_exhaustive() // Show that some other field(s) exist.
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(10, "secret!".to_owned())),
|
||||
/// "Foo(10, ..)",
|
||||
/// );
|
||||
/// ```
|
||||
#[unstable(feature = "debug_more_non_exhaustive", issue = "127942")]
|
||||
pub fn finish_non_exhaustive(&mut self) -> fmt::Result {
|
||||
self.result = self.result.and_then(|_| {
|
||||
if self.fields > 0 {
|
||||
if self.is_pretty() {
|
||||
let mut slot = None;
|
||||
let mut state = Default::default();
|
||||
let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state);
|
||||
writer.write_str("..\n")?;
|
||||
self.fmt.write_str(")")
|
||||
} else {
|
||||
self.fmt.write_str(", ..)")
|
||||
}
|
||||
} else {
|
||||
self.fmt.write_str("(..)")
|
||||
}
|
||||
});
|
||||
self.result
|
||||
}
|
||||
|
||||
/// Finishes output and returns any error encountered.
|
||||
///
|
||||
/// # Examples
|
||||
@ -554,6 +599,56 @@ pub fn entries<D, I>(&mut self, entries: I) -> &mut Self
|
||||
self
|
||||
}
|
||||
|
||||
/// Marks the set as non-exhaustive, indicating to the reader that there are some other
|
||||
/// elements that are not shown in the debug representation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(debug_more_non_exhaustive)]
|
||||
///
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<i32>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// // Print at most two elements, abbreviate the rest
|
||||
/// let mut f = fmt.debug_set();
|
||||
/// let mut f = f.entries(self.0.iter().take(2));
|
||||
/// if self.0.len() > 2 {
|
||||
/// f.finish_non_exhaustive()
|
||||
/// } else {
|
||||
/// f.finish()
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(vec![1, 2, 3, 4])),
|
||||
/// "{1, 2, ..}",
|
||||
/// );
|
||||
/// ```
|
||||
#[unstable(feature = "debug_more_non_exhaustive", issue = "127942")]
|
||||
pub fn finish_non_exhaustive(&mut self) -> fmt::Result {
|
||||
self.inner.result = self.inner.result.and_then(|_| {
|
||||
if self.inner.has_fields {
|
||||
if self.inner.is_pretty() {
|
||||
let mut slot = None;
|
||||
let mut state = Default::default();
|
||||
let mut writer = PadAdapter::wrap(self.inner.fmt, &mut slot, &mut state);
|
||||
writer.write_str("..\n")?;
|
||||
self.inner.fmt.write_str("}")
|
||||
} else {
|
||||
self.inner.fmt.write_str(", ..}")
|
||||
}
|
||||
} else {
|
||||
self.inner.fmt.write_str("..}")
|
||||
}
|
||||
});
|
||||
self.inner.result
|
||||
}
|
||||
|
||||
/// Finishes output and returns any error encountered.
|
||||
///
|
||||
/// # Examples
|
||||
@ -697,6 +792,55 @@ pub fn entries<D, I>(&mut self, entries: I) -> &mut Self
|
||||
self
|
||||
}
|
||||
|
||||
/// Marks the list as non-exhaustive, indicating to the reader that there are some other
|
||||
/// elements that are not shown in the debug representation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(debug_more_non_exhaustive)]
|
||||
///
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<i32>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// // Print at most two elements, abbreviate the rest
|
||||
/// let mut f = fmt.debug_list();
|
||||
/// let mut f = f.entries(self.0.iter().take(2));
|
||||
/// if self.0.len() > 2 {
|
||||
/// f.finish_non_exhaustive()
|
||||
/// } else {
|
||||
/// f.finish()
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(vec![1, 2, 3, 4])),
|
||||
/// "[1, 2, ..]",
|
||||
/// );
|
||||
/// ```
|
||||
#[unstable(feature = "debug_more_non_exhaustive", issue = "127942")]
|
||||
pub fn finish_non_exhaustive(&mut self) -> fmt::Result {
|
||||
self.inner.result.and_then(|_| {
|
||||
if self.inner.has_fields {
|
||||
if self.inner.is_pretty() {
|
||||
let mut slot = None;
|
||||
let mut state = Default::default();
|
||||
let mut writer = PadAdapter::wrap(self.inner.fmt, &mut slot, &mut state);
|
||||
writer.write_str("..\n")?;
|
||||
self.inner.fmt.write_str("]")
|
||||
} else {
|
||||
self.inner.fmt.write_str(", ..]")
|
||||
}
|
||||
} else {
|
||||
self.inner.fmt.write_str("..]")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Finishes output and returns any error encountered.
|
||||
///
|
||||
/// # Examples
|
||||
@ -973,6 +1117,62 @@ pub fn entries<K, V, I>(&mut self, entries: I) -> &mut Self
|
||||
self
|
||||
}
|
||||
|
||||
/// Marks the map as non-exhaustive, indicating to the reader that there are some other
|
||||
/// entries that are not shown in the debug representation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(debug_more_non_exhaustive)]
|
||||
///
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<(String, i32)>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// // Print at most two elements, abbreviate the rest
|
||||
/// let mut f = fmt.debug_map();
|
||||
/// let mut f = f.entries(self.0.iter().take(2).map(|&(ref k, ref v)| (k, v)));
|
||||
/// if self.0.len() > 2 {
|
||||
/// f.finish_non_exhaustive()
|
||||
/// } else {
|
||||
/// f.finish()
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(vec![
|
||||
/// ("A".to_string(), 10),
|
||||
/// ("B".to_string(), 11),
|
||||
/// ("C".to_string(), 12),
|
||||
/// ])),
|
||||
/// r#"{"A": 10, "B": 11, ..}"#,
|
||||
/// );
|
||||
/// ```
|
||||
#[unstable(feature = "debug_more_non_exhaustive", issue = "127942")]
|
||||
pub fn finish_non_exhaustive(&mut self) -> fmt::Result {
|
||||
self.result = self.result.and_then(|_| {
|
||||
assert!(!self.has_key, "attempted to finish a map with a partial entry");
|
||||
|
||||
if self.has_fields {
|
||||
if self.is_pretty() {
|
||||
let mut slot = None;
|
||||
let mut state = Default::default();
|
||||
let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state);
|
||||
writer.write_str("..\n")?;
|
||||
self.fmt.write_str("}")
|
||||
} else {
|
||||
self.fmt.write_str(", ..}")
|
||||
}
|
||||
} else {
|
||||
self.fmt.write_str("..}")
|
||||
}
|
||||
});
|
||||
self.result
|
||||
}
|
||||
|
||||
/// Finishes output and returns any error encountered.
|
||||
///
|
||||
/// # Panics
|
||||
|
@ -257,6 +257,80 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
10/20,
|
||||
),
|
||||
"world",
|
||||
)"#,
|
||||
format!("{Bar:#?}")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_non_exhaustive() {
|
||||
struct Foo;
|
||||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_tuple("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_tuple("Foo")
|
||||
.field(&true)
|
||||
.field(&format_args!("{}/{}", 10, 20))
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("Foo(true, 10/20, ..)", format!("{Foo:?}"));
|
||||
assert_eq!(
|
||||
"Foo(
|
||||
true,
|
||||
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_tuple("Foo")
|
||||
.field(&true)
|
||||
.field(&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_tuple("Bar").field(&Foo).field(&"world").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(r#"Bar(Foo(true, 10/20, ..), "world", ..)"#, format!("{Bar:?}"));
|
||||
assert_eq!(
|
||||
r#"Bar(
|
||||
Foo(
|
||||
true,
|
||||
10/20,
|
||||
..
|
||||
),
|
||||
"world",
|
||||
..
|
||||
)"#,
|
||||
format!("{Bar:#?}")
|
||||
);
|
||||
@ -371,8 +445,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
r#"{"foo": {"bar": true, 10: 10/20}, \
|
||||
{"bar": true, 10: 10/20}: "world"}"#,
|
||||
r#"{"foo": {"bar": true, 10: 10/20}, {"bar": true, 10: 10/20}: "world"}"#,
|
||||
format!("{Bar:?}")
|
||||
);
|
||||
assert_eq!(
|
||||
@ -471,6 +544,103 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
||||
let _ = format!("{Foo:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_non_exhaustive() {
|
||||
struct Foo;
|
||||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_map().finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("{..}", format!("{Foo:?}"));
|
||||
assert_eq!("{..}", format!("{Foo:#?}"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiple_and_non_exhaustive() {
|
||||
struct Entry;
|
||||
|
||||
impl fmt::Debug for Entry {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_map()
|
||||
.entry(&"bar", &true)
|
||||
.entry(&10, &format_args!("{}/{}", 10, 20))
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
struct KeyValue;
|
||||
|
||||
impl fmt::Debug for KeyValue {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_map()
|
||||
.key(&"bar")
|
||||
.value(&true)
|
||||
.key(&10)
|
||||
.value(&format_args!("{}/{}", 10, 20))
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(format!("{Entry:?}"), format!("{KeyValue:?}"));
|
||||
assert_eq!(format!("{Entry:#?}"), format!("{KeyValue:#?}"));
|
||||
|
||||
assert_eq!(r#"{"bar": true, 10: 10/20, ..}"#, format!("{Entry:?}"));
|
||||
assert_eq!(
|
||||
r#"{
|
||||
"bar": true,
|
||||
10: 10/20,
|
||||
..
|
||||
}"#,
|
||||
format!("{Entry:#?}")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nested_non_exhaustive() {
|
||||
struct Foo;
|
||||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_map()
|
||||
.entry(&"bar", &true)
|
||||
.entry(&10, &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_map().entry(&"foo", &Foo).entry(&Foo, &"world").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
r#"{"foo": {"bar": true, 10: 10/20, ..}, {"bar": true, 10: 10/20, ..}: "world", ..}"#,
|
||||
format!("{Bar:?}")
|
||||
);
|
||||
assert_eq!(
|
||||
r#"{
|
||||
"foo": {
|
||||
"bar": true,
|
||||
10: 10/20,
|
||||
..
|
||||
},
|
||||
{
|
||||
"bar": true,
|
||||
10: 10/20,
|
||||
..
|
||||
}: "world",
|
||||
..
|
||||
}"#,
|
||||
format!("{Bar:#?}")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
mod debug_set {
|
||||
@ -555,6 +725,80 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
10/20,
|
||||
},
|
||||
"world",
|
||||
}"#,
|
||||
format!("{Bar:#?}")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_non_exhaustive() {
|
||||
struct Foo;
|
||||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_set().finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("{..}", format!("{Foo:?}"));
|
||||
assert_eq!("{..}", 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_set()
|
||||
.entry(&true)
|
||||
.entry(&format_args!("{}/{}", 10, 20))
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("{true, 10/20, ..}", format!("{Foo:?}"));
|
||||
assert_eq!(
|
||||
"{
|
||||
true,
|
||||
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_set()
|
||||
.entry(&true)
|
||||
.entry(&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_set().entry(&Foo).entry(&"world").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(r#"{{true, 10/20, ..}, "world", ..}"#, format!("{Bar:?}"));
|
||||
assert_eq!(
|
||||
r#"{
|
||||
{
|
||||
true,
|
||||
10/20,
|
||||
..
|
||||
},
|
||||
"world",
|
||||
..
|
||||
}"#,
|
||||
format!("{Bar:#?}")
|
||||
);
|
||||
@ -643,6 +887,80 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
10/20,
|
||||
],
|
||||
"world",
|
||||
]"#,
|
||||
format!("{Bar:#?}")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_non_exhaustive() {
|
||||
struct Foo;
|
||||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_list().finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("[..]", format!("{Foo:?}"));
|
||||
assert_eq!("[..]", format!("{Foo:#?}"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiple_non_exhaustive() {
|
||||
struct Foo;
|
||||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_list()
|
||||
.entry(&true)
|
||||
.entry(&format_args!("{}/{}", 10, 20))
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!("[true, 10/20, ..]", format!("{Foo:?}"));
|
||||
assert_eq!(
|
||||
"[
|
||||
true,
|
||||
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_list()
|
||||
.entry(&true)
|
||||
.entry(&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_list().entry(&Foo).entry(&"world").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(r#"[[true, 10/20, ..], "world", ..]"#, format!("{Bar:?}"));
|
||||
assert_eq!(
|
||||
r#"[
|
||||
[
|
||||
true,
|
||||
10/20,
|
||||
..
|
||||
],
|
||||
"world",
|
||||
..
|
||||
]"#,
|
||||
format!("{Bar:#?}")
|
||||
);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#![feature(core_io_borrowed_buf)]
|
||||
#![feature(core_private_bignum)]
|
||||
#![feature(core_private_diy_float)]
|
||||
#![feature(debug_more_non_exhaustive)]
|
||||
#![feature(dec2flt)]
|
||||
#![feature(duration_consts_float)]
|
||||
#![feature(duration_constants)]
|
||||
|
Loading…
Reference in New Issue
Block a user