diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index a092bfb3b0a8a..441584b02bf15 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -528,6 +528,9 @@ pub use core::fmt::{ArgumentV1, Arguments, write}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; +#[unstable(feature = "display_as_debug", issue = "49128")] +pub use core::fmt::DisplayAsDebug; + use string; /// The `format` function takes an [`Arguments`] struct and returns the resulting diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index b93e128d50819..8532e56b36eb7 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -94,6 +94,7 @@ #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] #![feature(fmt_internals)] +#![feature(display_as_debug)] #![feature(from_ref)] #![feature(fundamental)] #![feature(generic_param_attrs)] diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index a1f4c6995dae0..29a0a4c4e4286 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -537,3 +537,70 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { self.fmt.alternate() } } + +/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations. +/// +/// This is useful you need to use the `Display` `impl` of a type in a `Debug` +/// context instead of the `Debug` `impl` of the type. One such scenario where +/// this is useful is when you need an unquoted string as part of your +/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation. As seen +/// below in the example, this can happen when you want to use [`.debug_set()`] +/// methods and friends. +/// +/// [`.debug_set()`]: struct.Formatter.html#method.debug_set +/// +/// The difference between `&'a str` and `DisplayAsDebug<&'a str>` in a `Debug` +/// context such as `println!("{:?}", )` is that the former will quote +/// the string while the latter will not. In other words, the following holds: +/// +/// ```rust +/// #![feature(display_as_debug)] +/// use std::fmt::DisplayAsDebug; +/// +/// assert_eq!("foo", format!("{:?}", DisplayAsDebug("foo"))); +/// assert_eq!("\"foo\"", format!("{:?}", "foo")); +/// ``` +/// +/// # Examples +/// +/// In this example we use `DisplayAsDebug("_")` for a "catch all" match arm. +/// +/// ```rust +/// #![feature(display_as_debug)] +/// use std::fmt::{Debug, Formatter, DisplayAsDebug, Result}; +/// +/// struct Arm<'a, L: 'a, R: 'a>(&'a (L, R)); +/// struct Table<'a, K: 'a, V: 'a>(&'a [(K, V)], V); +/// +/// impl<'a, L: 'a + Debug, R: 'a + Debug> Debug for Arm<'a, L, R> { +/// fn fmt(&self, fmt: &mut Formatter) -> Result { +/// L::fmt(&(self.0).0, fmt)?; +/// fmt.write_str(" => ")?; +/// R::fmt(&(self.0).1, fmt) +/// } +/// } +/// +/// impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for Table<'a, K, V> { +/// fn fmt(&self, fmt: &mut Formatter) -> Result { +/// fmt.debug_set() +/// .entries(self.0.iter().map(Arm)) +/// .entry(&Arm(&(DisplayAsDebug("_"), &self.1))) +/// .finish() +/// } +/// } +/// +/// let table = (1..3).enumerate().collect::>(); +/// assert_eq!(format!("{:?}", Table(&*table, 0)), +/// "{0 => 1, 1 => 2, _ => 0}"); +/// ``` +#[unstable(feature = "display_as_debug", issue = "49128")] +#[must_use] +#[derive(Copy, Clone)] +pub struct DisplayAsDebug(pub T); + +#[unstable(feature = "display_as_debug", issue = "49128")] +impl fmt::Debug for DisplayAsDebug { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + ::fmt(&self.0, fmt) + } +} diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 67126b496e211..d5f5aa48f11e7 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -42,6 +42,9 @@ pub enum Alignment { #[stable(feature = "debug_builders", since = "1.2.0")] pub use self::builders::{DebugStruct, DebugTuple, DebugSet, DebugList, DebugMap}; +#[unstable(feature = "display_as_debug", issue = "49128")] +pub use self::builders::DisplayAsDebug; + #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")] #[doc(hidden)]