Rollup merge of #127945 - tgross35:debug-more-non-exhaustive, r=Noratrieb

Implement `debug_more_non_exhaustive`

This implements the ACP at https://github.com/rust-lang/libs-team/issues/248, adding `.finish_non_exhaustive()` for `DebugTuple`, `DebugSet`, `DebugList`, and `DebugMap`.

Also used this as an opportunity to make some documentation and tests more readable by using raw strings instead of escaped quotes.

Tracking issue: https://github.com/rust-lang/rust/issues/127942
This commit is contained in:
Matthias Krüger 2024-08-21 19:35:10 +02:00 committed by GitHub
commit 65386c045e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 565 additions and 46 deletions

View File

@ -78,7 +78,7 @@ impl fmt::Write for PadAdapter<'_, '_> {
///
/// assert_eq!(
/// format!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }),
/// "Foo { bar: 10, baz: \"Hello World\" }",
/// r#"Foo { bar: 10, baz: "Hello World" }"#,
/// );
/// ```
#[must_use = "must eventually call `finish()` on Debug builders"]
@ -125,7 +125,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
///
/// assert_eq!(
/// format!("{:?}", Bar { bar: 10, another: "Hello World".to_string() }),
/// "Bar { bar: 10, another: \"Hello World\", nonexistent_field: 1 }",
/// r#"Bar { bar: 10, another: "Hello World", nonexistent_field: 1 }"#,
/// );
/// ```
#[stable(feature = "debug_builders", since = "1.2.0")]
@ -237,7 +237,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
///
/// assert_eq!(
/// format!("{:?}", Bar { bar: 10, baz: "Hello World".to_string() }),
/// "Bar { bar: 10, baz: \"Hello World\" }",
/// r#"Bar { bar: 10, baz: "Hello World" }"#,
/// );
/// ```
#[stable(feature = "debug_builders", since = "1.2.0")]
@ -280,7 +280,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
///
/// assert_eq!(
/// format!("{:?}", Foo(10, "Hello World".to_string())),
/// "Foo(10, \"Hello World\")",
/// r#"Foo(10, "Hello World")"#,
/// );
/// ```
#[must_use = "must eventually call `finish()` on Debug builders"]
@ -322,7 +322,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
///
/// assert_eq!(
/// format!("{:?}", Foo(10, "Hello World".to_string())),
/// "Foo(10, \"Hello World\")",
/// r#"Foo(10, "Hello World")"#,
/// );
/// ```
#[stable(feature = "debug_builders", since = "1.2.0")]
@ -360,6 +360,51 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
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
@ -381,7 +426,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
///
/// assert_eq!(
/// format!("{:?}", Foo(10, "Hello World".to_string())),
/// "Foo(10, \"Hello World\")",
/// r#"Foo(10, "Hello World")"#,
/// );
/// ```
#[stable(feature = "debug_builders", since = "1.2.0")]
@ -555,6 +600,56 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
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
@ -699,6 +794,55 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
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
@ -750,7 +894,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
///
/// assert_eq!(
/// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
/// "{\"A\": 10, \"B\": 11}",
/// r#"{"A": 10, "B": 11}"#,
/// );
/// ```
#[must_use = "must eventually call `finish()` on Debug builders"]
@ -790,7 +934,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
///
/// assert_eq!(
/// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
/// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}",
/// r#"{"whole": [("A", 10), ("B", 11)]}"#,
/// );
/// ```
#[stable(feature = "debug_builders", since = "1.2.0")]
@ -826,7 +970,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
///
/// assert_eq!(
/// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
/// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}",
/// r#"{"whole": [("A", 10), ("B", 11)]}"#,
/// );
/// ```
#[stable(feature = "debug_map_key_value", since = "1.42.0")]
@ -902,7 +1046,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
///
/// assert_eq!(
/// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
/// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}",
/// r#"{"whole": [("A", 10), ("B", 11)]}"#,
/// );
/// ```
#[stable(feature = "debug_map_key_value", since = "1.42.0")]
@ -960,7 +1104,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
///
/// assert_eq!(
/// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
/// "{\"A\": 10, \"B\": 11}",
/// r#"{"A": 10, "B": 11}"#,
/// );
/// ```
#[stable(feature = "debug_builders", since = "1.2.0")]
@ -976,6 +1120,62 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
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
@ -1000,7 +1200,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
///
/// assert_eq!(
/// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
/// "{\"A\": 10, \"B\": 11}",
/// r#"{"A": 10, "B": 11}"#,
/// );
/// ```
#[stable(feature = "debug_builders", since = "1.2.0")]

View File

@ -79,23 +79,23 @@ mod debug_struct {
}
assert_eq!(
"Bar { foo: Foo { bar: true, baz: 10/20 }, hello: \"world\" }",
r#"Bar { foo: Foo { bar: true, baz: 10/20 }, hello: "world" }"#,
format!("{Bar:?}")
);
assert_eq!(
"Bar {
r#"Bar {
foo: Foo {
bar: true,
baz: 10/20,
},
hello: \"world\",
}",
hello: "world",
}"#,
format!("{Bar:#?}")
);
}
#[test]
fn test_only_non_exhaustive() {
fn test_empty_non_exhaustive() {
struct Foo;
impl fmt::Debug for Foo {
@ -157,19 +157,19 @@ mod debug_struct {
}
assert_eq!(
"Bar { foo: Foo { bar: true, baz: 10/20, .. }, hello: \"world\", .. }",
r#"Bar { foo: Foo { bar: true, baz: 10/20, .. }, hello: "world", .. }"#,
format!("{Bar:?}")
);
assert_eq!(
"Bar {
r#"Bar {
foo: Foo {
bar: true,
baz: 10/20,
..
},
hello: \"world\",
hello: "world",
..
}",
}"#,
format!("{Bar:#?}")
);
}
@ -249,15 +249,89 @@ mod debug_tuple {
}
}
assert_eq!("Bar(Foo(true, 10/20), \"world\")", format!("{Bar:?}"));
assert_eq!(r#"Bar(Foo(true, 10/20), "world")"#, format!("{Bar:?}"));
assert_eq!(
"Bar(
r#"Bar(
Foo(
true,
10/20,
),
\"world\",
"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:#?}")
);
}
@ -301,11 +375,11 @@ mod debug_map {
assert_eq!(format!("{Entry:?}"), format!("{KeyValue:?}"));
assert_eq!(format!("{Entry:#?}"), format!("{KeyValue:#?}"));
assert_eq!("{\"bar\": true}", format!("{Entry:?}"));
assert_eq!(r#"{"bar": true}"#, format!("{Entry:?}"));
assert_eq!(
"{
\"bar\": true,
}",
r#"{
"bar": true,
}"#,
format!("{Entry:#?}")
);
}
@ -339,12 +413,12 @@ mod debug_map {
assert_eq!(format!("{Entry:?}"), format!("{KeyValue:?}"));
assert_eq!(format!("{Entry:#?}"), format!("{KeyValue:#?}"));
assert_eq!("{\"bar\": true, 10: 10/20}", format!("{Entry:?}"));
assert_eq!(r#"{"bar": true, 10: 10/20}"#, format!("{Entry:?}"));
assert_eq!(
"{
\"bar\": true,
r#"{
"bar": true,
10: 10/20,
}",
}"#,
format!("{Entry:#?}")
);
}
@ -371,21 +445,20 @@ mod debug_map {
}
assert_eq!(
"{\"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!(
"{
\"foo\": {
\"bar\": true,
r#"{
"foo": {
"bar": true,
10: 10/20,
},
{
\"bar\": true,
"bar": true,
10: 10/20,
}: \"world\",
}",
}: "world",
}"#,
format!("{Bar:#?}")
);
}
@ -471,6 +544,103 @@ mod debug_map {
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 {
@ -547,15 +717,89 @@ mod debug_set {
}
}
assert_eq!("{{true, 10/20}, \"world\"}", format!("{Bar:?}"));
assert_eq!(r#"{{true, 10/20}, "world"}"#, format!("{Bar:?}"));
assert_eq!(
"{
r#"{
{
true,
10/20,
},
\"world\",
"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:#?}")
);
}
@ -635,15 +879,89 @@ mod debug_list {
}
}
assert_eq!("[[true, 10/20], \"world\"]", format!("{Bar:?}"));
assert_eq!(r#"[[true, 10/20], "world"]"#, format!("{Bar:?}"));
assert_eq!(
"[
r#"[
[
true,
10/20,
],
\"world\",
"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:#?}")
);
}

View File

@ -43,6 +43,7 @@
#![feature(core_io_borrowed_buf)]
#![feature(core_private_bignum)]
#![feature(core_private_diy_float)]
#![feature(debug_more_non_exhaustive)]
#![feature(dec2flt)]
#![feature(duration_constants)]
#![feature(duration_constructors)]