diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index d2b45f4b0492b..e1d007f0ac497 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -904,14 +904,7 @@ impl Ord for BTreeMap { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for BTreeMap { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{{")); - - for (i, (k, v)) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{:?}: {:?}", *k, *v)); - } - - write!(f, "}}") + self.iter().fold(f.debug_map(), |b, (k, v)| b.entry(k, v)).finish() } } diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 08ee5801482fd..840110b5b276f 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -628,14 +628,7 @@ impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet> for &'a BTreeSet { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for BTreeSet { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{{")); - - for (i, x) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{:?}", *x)); - } - - write!(f, "}}") + self.iter().fold(f.debug_set(), |b, e| b.entry(e)).finish() } } diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index f774c1505b82b..c769b3df37f62 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -40,6 +40,7 @@ #![feature(str_char)] #![feature(convert)] #![feature(slice_patterns)] +#![feature(debug_builders)] #![cfg_attr(test, feature(rand, rustc_private, test, hash, collections))] #![cfg_attr(test, allow(deprecated))] // rand diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 908c78a17f4f9..581bab5759fd7 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -927,14 +927,7 @@ impl Clone for LinkedList { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for LinkedList { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "[")); - - for (i, e) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{:?}", *e)); - } - - write!(f, "]") + self.iter().fold(f.debug_list(), |b, e| b.entry(e)).finish() } } diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index 07f029cc15e2f..f61a7f2d30c62 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -177,22 +177,54 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { } } +struct DebugInner<'a, 'b: 'a> { + fmt: &'a mut fmt::Formatter<'b>, + result: fmt::Result, + has_fields: bool, +} + +impl<'a, 'b: 'a> DebugInner<'a, 'b> { + fn entry(&mut self, entry: &fmt::Debug) { + self.result = self.result.and_then(|_| { + if self.is_pretty() { + let mut writer = PadAdapter::new(self.fmt); + let prefix = if self.has_fields { "," } else { "" }; + fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, entry)) + } else { + let prefix = if self.has_fields { ", " } else { "" }; + write!(self.fmt, "{}{:?}", prefix, entry) + } + }); + + self.has_fields = true; + } + + pub fn finish(&mut self) { + let prefix = if self.is_pretty() && self.has_fields { "\n" } else { "" }; + self.result = self.result.and_then(|_| self.fmt.write_str(prefix)); + } + + fn is_pretty(&self) -> bool { + self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0 + } +} + /// A struct to help with `fmt::Debug` implementations. /// /// Constructed by the `Formatter::debug_set` method. #[must_use] pub struct DebugSet<'a, 'b: 'a> { - fmt: &'a mut fmt::Formatter<'b>, - result: fmt::Result, - has_fields: bool, + inner: DebugInner<'a, 'b>, } -pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugSet<'a, 'b> { - let result = write!(fmt, "{} {{", name); +pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> { + let result = write!(fmt, "{{"); DebugSet { - fmt: fmt, - result: result, - has_fields: false, + inner: DebugInner { + fmt: fmt, + result: result, + has_fields: false, + } } } @@ -200,41 +232,52 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// Adds a new entry to the set output. #[unstable(feature = "debug_builders", reason = "method was just created")] pub fn entry(mut self, entry: &fmt::Debug) -> DebugSet<'a, 'b> { - self.result = self.result.and_then(|_| { - let prefix = if self.has_fields { - "," - } else { - "" - }; - - if self.is_pretty() { - let mut writer = PadAdapter::new(self.fmt); - fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, entry)) - } else { - write!(self.fmt, "{} {:?}", prefix, entry) - } - }); - - self.has_fields = true; + self.inner.entry(entry); self } /// Consumes the `DebugSet`, finishing output and returning any error /// encountered. #[unstable(feature = "debug_builders", reason = "method was just created")] - pub fn finish(self) -> fmt::Result { - self.result.and_then(|_| { - let end = match (self.has_fields, self.is_pretty()) { - (false, _) => "}", - (true, false) => " }", - (true, true) => "\n}", - }; - self.fmt.write_str(end) - }) + pub fn finish(mut self) -> fmt::Result { + self.inner.finish(); + self.inner.result.and_then(|_| self.inner.fmt.write_str("}")) } +} - fn is_pretty(&self) -> bool { - self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0 +/// A struct to help with `fmt::Debug` implementations. +/// +/// Constructed by the `Formatter::debug_list` method. +#[must_use] +pub struct DebugList<'a, 'b: 'a> { + inner: DebugInner<'a, 'b>, +} + +pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> { + let result = write!(fmt, "["); + DebugList { + inner: DebugInner { + fmt: fmt, + result: result, + has_fields: false, + } + } +} + +impl<'a, 'b: 'a> DebugList<'a, 'b> { + /// Adds a new entry to the set output. + #[unstable(feature = "debug_builders", reason = "method was just created")] + pub fn entry(mut self, entry: &fmt::Debug) -> DebugList<'a, 'b> { + self.inner.entry(entry); + self + } + + /// Consumes the `DebugSet`, finishing output and returning any error + /// encountered. + #[unstable(feature = "debug_builders", reason = "method was just created")] + pub fn finish(mut self) -> fmt::Result { + self.inner.finish(); + self.inner.result.and_then(|_| self.inner.fmt.write_str("]")) } } @@ -248,8 +291,8 @@ pub struct DebugMap<'a, 'b: 'a> { has_fields: bool, } -pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugMap<'a, 'b> { - let result = write!(fmt, "{} {{", name); +pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> { + let result = write!(fmt, "{{"); DebugMap { fmt: fmt, result: result, @@ -262,22 +305,17 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { #[unstable(feature = "debug_builders", reason = "method was just created")] pub fn entry(mut self, key: &fmt::Debug, value: &fmt::Debug) -> DebugMap<'a, 'b> { self.result = self.result.and_then(|_| { - let prefix = if self.has_fields { - "," - } else { - "" - }; - if self.is_pretty() { let mut writer = PadAdapter::new(self.fmt); + let prefix = if self.has_fields { "," } else { "" }; fmt::write(&mut writer, format_args!("{}\n{:#?}: {:#?}", prefix, key, value)) } else { - write!(self.fmt, "{} {:?}: {:?}", prefix, key, value) + let prefix = if self.has_fields { ", " } else { "" }; + write!(self.fmt, "{}{:?}: {:?}", prefix, key, value) } }); self.has_fields = true; - self } @@ -285,14 +323,8 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// encountered. #[unstable(feature = "debug_builders", reason = "method was just created")] pub fn finish(self) -> fmt::Result { - self.result.and_then(|_| { - let end = match (self.has_fields, self.is_pretty()) { - (false, _) => "}", - (true, false) => " }", - (true, true) => "\n}", - }; - self.fmt.write_str(end) - }) + let prefix = if self.is_pretty() && self.has_fields { "\n" } else { "" }; + self.result.and_then(|_| write!(self.fmt, "{}}}", prefix)) } fn is_pretty(&self) -> bool { diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index aa0d0a1539a30..bd802cfb55948 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -32,7 +32,7 @@ pub use self::num::radix; pub use self::num::Radix; pub use self::num::RadixFmt; -pub use self::builders::{DebugStruct, DebugTuple, DebugSet, DebugMap}; +pub use self::builders::{DebugStruct, DebugTuple, DebugSet, DebugList, DebugMap}; mod num; mod float; @@ -644,7 +644,7 @@ impl<'a> Formatter<'a> { /// // prints "Foo { bar: 10, baz: "Hello World" }" /// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }); /// ``` - #[unstable(feature = "core", reason = "method was just created")] + #[unstable(feature = "debug_builders", reason = "method was just created")] #[inline] pub fn debug_struct<'b>(&'b mut self, name: &str) -> DebugStruct<'b, 'a> { builders::debug_struct_new(self, name) @@ -673,12 +673,38 @@ impl<'a> Formatter<'a> { /// // prints "Foo(10, "Hello World")" /// println!("{:?}", Foo(10, "Hello World".to_string())); /// ``` - #[unstable(feature = "core", reason = "method was just created")] + #[unstable(feature = "debug_builders", reason = "method was just created")] #[inline] pub fn debug_tuple<'b>(&'b mut self, name: &str) -> DebugTuple<'b, 'a> { builders::debug_tuple_new(self, name) } + /// Creates a `DebugList` builder designed to assist with creation of + /// `fmt::Debug` implementations for list-like structures. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(debug_builders, core)] + /// use std::fmt; + /// + /// struct Foo(Vec); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// self.0.iter().fold(fmt.debug_list(), |b, e| b.entry(e)).finish() + /// } + /// } + /// + /// // prints "[10, 11]" + /// println!("{:?}", Foo(vec![10, 11])); + /// ``` + #[unstable(feature = "debug_builders", reason = "method was just created")] + #[inline] + pub fn debug_list<'b>(&'b mut self) -> DebugList<'b, 'a> { + builders::debug_list_new(self) + } + /// Creates a `DebugSet` builder designed to assist with creation of /// `fmt::Debug` implementations for set-like structures. /// @@ -692,21 +718,17 @@ impl<'a> Formatter<'a> { /// /// impl fmt::Debug for Foo { /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - /// let mut builder = fmt.debug_set("Foo"); - /// for i in &self.0 { - /// builder = builder.entry(i); - /// } - /// builder.finish() + /// self.0.iter().fold(fmt.debug_set(), |b, e| b.entry(e)).finish() /// } /// } /// - /// // prints "Foo { 10, 11 }" + /// // prints "{10, 11}" /// println!("{:?}", Foo(vec![10, 11])); /// ``` - #[unstable(feature = "core", reason = "method was just created")] + #[unstable(feature = "debug_builders", reason = "method was just created")] #[inline] - pub fn debug_set<'b>(&'b mut self, name: &str) -> DebugSet<'b, 'a> { - builders::debug_set_new(self, name) + pub fn debug_set<'b>(&'b mut self) -> DebugSet<'b, 'a> { + builders::debug_set_new(self) } /// Creates a `DebugMap` builder designed to assist with creation of @@ -722,21 +744,17 @@ impl<'a> Formatter<'a> { /// /// impl fmt::Debug for Foo { /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - /// let mut builder = fmt.debug_map("Foo"); - /// for &(ref key, ref value) in &self.0 { - /// builder = builder.entry(key, value); - /// } - /// builder.finish() + /// self.0.iter().fold(fmt.debug_map(), |b, &(ref k, ref v)| b.entry(k, v)).finish() /// } /// } /// - /// // prints "Foo { "A": 10, "B": 11 }" + /// // prints "{"A": 10, "B": 11}" /// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])); /// ``` - #[unstable(feature = "core", reason = "method was just created")] + #[unstable(feature = "debug_builders", reason = "method was just created")] #[inline] - pub fn debug_map<'b>(&'b mut self, name: &str) -> DebugMap<'b, 'a> { - builders::debug_map_new(self, name) + pub fn debug_map<'b>(&'b mut self) -> DebugMap<'b, 'a> { + builders::debug_map_new(self) } } @@ -987,22 +1005,7 @@ impl<'a> Debug for &'a (any::Any+'a) { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for [T] { fn fmt(&self, f: &mut Formatter) -> Result { - if f.flags & (1 << (FlagV1::Alternate as u32)) == 0 { - try!(write!(f, "[")); - } - let mut is_first = true; - for x in self { - if is_first { - is_first = false; - } else { - try!(write!(f, ", ")); - } - try!(write!(f, "{:?}", *x)) - } - if f.flags & (1 << (FlagV1::Alternate as u32)) == 0 { - try!(write!(f, "]")); - } - Ok(()) + self.iter().fold(f.debug_list(), |b, e| b.entry(e)).finish() } } diff --git a/src/libcoretest/fmt/builders.rs b/src/libcoretest/fmt/builders.rs index b2fbc90be5914..885ee3f9c3be2 100644 --- a/src/libcoretest/fmt/builders.rs +++ b/src/libcoretest/fmt/builders.rs @@ -211,12 +211,12 @@ mod debug_map { impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_map("Foo").finish() + fmt.debug_map().finish() } } - assert_eq!("Foo {}", format!("{:?}", Foo)); - assert_eq!("Foo {}", format!("{:#?}", Foo)); + assert_eq!("{}", format!("{:?}", Foo)); + assert_eq!("{}", format!("{:#?}", Foo)); } #[test] @@ -225,15 +225,15 @@ mod debug_map { impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_map("Foo") + fmt.debug_map() .entry(&"bar", &true) .finish() } } - assert_eq!("Foo { \"bar\": true }", format!("{:?}", Foo)); + assert_eq!("{\"bar\": true}", format!("{:?}", Foo)); assert_eq!( -"Foo { +"{ \"bar\": true }", format!("{:#?}", Foo)); @@ -245,16 +245,16 @@ mod debug_map { impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_map("Foo") + fmt.debug_map() .entry(&"bar", &true) .entry(&10i32, &format_args!("{}/{}", 10i32, 20i32)) .finish() } } - assert_eq!("Foo { \"bar\": true, 10: 10/20 }", format!("{:?}", Foo)); + assert_eq!("{\"bar\": true, 10: 10/20}", format!("{:?}", Foo)); assert_eq!( -"Foo { +"{ \"bar\": true, 10: 10/20 }", @@ -267,7 +267,7 @@ mod debug_map { impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_map("Foo") + fmt.debug_map() .entry(&"bar", &true) .entry(&10i32, &format_args!("{}/{}", 10i32, 20i32)) .finish() @@ -278,23 +278,23 @@ mod debug_map { impl fmt::Debug for Bar { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_map("Bar") + fmt.debug_map() .entry(&"foo", &Foo) .entry(&Foo, &"world") .finish() } } - assert_eq!("Bar { \"foo\": Foo { \"bar\": true, 10: 10/20 }, \ - Foo { \"bar\": true, 10: 10/20 }: \"world\" }", + assert_eq!("{\"foo\": {\"bar\": true, 10: 10/20}, \ + {\"bar\": true, 10: 10/20}: \"world\"}", format!("{:?}", Bar)); assert_eq!( -"Bar { - \"foo\": Foo { +"{ + \"foo\": { \"bar\": true, 10: 10/20 }, - Foo { + { \"bar\": true, 10: 10/20 }: \"world\" @@ -312,12 +312,12 @@ mod debug_set { impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_set("Foo").finish() + fmt.debug_set().finish() } } - assert_eq!("Foo {}", format!("{:?}", Foo)); - assert_eq!("Foo {}", format!("{:#?}", Foo)); + assert_eq!("{}", format!("{:?}", Foo)); + assert_eq!("{}", format!("{:#?}", Foo)); } #[test] @@ -326,15 +326,15 @@ mod debug_set { impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_set("Foo") + fmt.debug_set() .entry(&true) .finish() } } - assert_eq!("Foo { true }", format!("{:?}", Foo)); + assert_eq!("{true}", format!("{:?}", Foo)); assert_eq!( -"Foo { +"{ true }", format!("{:#?}", Foo)); @@ -346,16 +346,16 @@ mod debug_set { impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_set("Foo") + fmt.debug_set() .entry(&true) .entry(&format_args!("{}/{}", 10i32, 20i32)) .finish() } } - assert_eq!("Foo { true, 10/20 }", format!("{:?}", Foo)); + assert_eq!("{true, 10/20}", format!("{:?}", Foo)); assert_eq!( -"Foo { +"{ true, 10/20 }", @@ -368,7 +368,7 @@ mod debug_set { impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_set("Foo") + fmt.debug_set() .entry(&true) .entry(&format_args!("{}/{}", 10i32, 20i32)) .finish() @@ -379,18 +379,18 @@ mod debug_set { impl fmt::Debug for Bar { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_set("Bar") + fmt.debug_set() .entry(&Foo) .entry(&"world") .finish() } } - assert_eq!("Bar { Foo { true, 10/20 }, \"world\" }", + assert_eq!("{{true, 10/20}, \"world\"}", format!("{:?}", Bar)); assert_eq!( -"Bar { - Foo { +"{ + { true, 10/20 }, @@ -399,3 +399,100 @@ mod debug_set { format!("{:#?}", Bar)); } } + +mod debug_list { + use std::fmt; + + #[test] + fn test_empty() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_list().finish() + } + } + + assert_eq!("[]", format!("{:?}", Foo)); + assert_eq!("[]", format!("{:#?}", Foo)); + } + + #[test] + fn test_single() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_list() + .entry(&true) + .finish() + } + } + + assert_eq!("[true]", format!("{:?}", Foo)); + assert_eq!( +"[ + true +]", + format!("{:#?}", Foo)); + } + + #[test] + fn test_multiple() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_list() + .entry(&true) + .entry(&format_args!("{}/{}", 10i32, 20i32)) + .finish() + } + } + + assert_eq!("[true, 10/20]", format!("{:?}", Foo)); + assert_eq!( +"[ + true, + 10/20 +]", + format!("{:#?}", Foo)); + } + + #[test] + fn test_nested() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_list() + .entry(&true) + .entry(&format_args!("{}/{}", 10i32, 20i32)) + .finish() + } + } + + struct Bar; + + impl fmt::Debug for Bar { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_list() + .entry(&Foo) + .entry(&"world") + .finish() + } + } + + assert_eq!("[[true, 10/20], \"world\"]", + format!("{:?}", Bar)); + assert_eq!( +"[ + [ + true, + 10/20 + ], + \"world\" +]", + format!("{:#?}", Bar)); + } +} diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index f9e1cb877b60b..50f405ea3b8e9 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1226,14 +1226,7 @@ impl Debug for HashMap where K: Eq + Hash + Debug, V: Debug, S: HashState { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{{")); - - for (i, (k, v)) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{:?}: {:?}", *k, *v)); - } - - write!(f, "}}") + self.iter().fold(f.debug_map(), |b, (k, v)| b.entry(k, v)).finish() } } diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 0933b4f662a9d..d3dae88265a78 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -614,14 +614,7 @@ impl fmt::Debug for HashSet S: HashState { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{{")); - - for (i, x) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{:?}", *x)); - } - - write!(f, "}}") + self.iter().fold(f.debug_set(), |b, e| b.entry(e)).finish() } } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 5f5f2fed56732..b7cb8f9ed50fd 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -128,6 +128,7 @@ #![feature(into_cow)] #![feature(slice_patterns)] #![feature(std_misc)] +#![feature(debug_builders)] #![cfg_attr(test, feature(test, rustc_private, std_misc))] // Don't link to std. We are std.