From 5201e7cf8ac0c78bc8e4f0feb8f97e91b957a19e Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 21 Mar 2018 07:31:39 +0100 Subject: [PATCH 1/3] document format_args! behavior wrt. Display and Debug --- src/libcore/fmt/mod.rs | 72 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 3ecd73873c091..0363714c31b5c 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -406,6 +406,18 @@ impl<'a> Arguments<'a> { /// macro validates the format string at compile-time so usage of the [`write`] /// and [`format`] functions can be safely performed. /// +/// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug` +/// and `Display` contexts as seen below. The example also shows that `Debug` +/// and `Display` format to the same thing: the interpolated format string +/// in `format_args!`. +/// +/// ```rust +/// let display = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); +/// let debug = format!("{}", format_args!("{} foo {:?}", 1, 2)); +/// assert_eq!("1 foo 2", display); +/// assert_eq!(display, debug); +/// ``` +/// /// [`format_args!`]: ../../std/macro.format_args.html /// [`format`]: ../../std/fmt/fn.format.html /// [`write`]: ../../std/fmt/fn.write.html @@ -1553,10 +1565,12 @@ impl<'a> Formatter<'a> { /// /// ```rust /// use std::fmt; + /// use std::net::Ipv4Addr; /// /// struct Foo { /// bar: i32, /// baz: String, + /// addr: Ipv4Addr, /// } /// /// impl fmt::Debug for Foo { @@ -1564,12 +1578,19 @@ impl<'a> Formatter<'a> { /// fmt.debug_struct("Foo") /// .field("bar", &self.bar) /// .field("baz", &self.baz) + /// .field("addr", &format_args!("{}", self.addr)) /// .finish() /// } /// } /// - /// // prints "Foo { bar: 10, baz: "Hello World" }" - /// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }); + /// assert_eq!( + /// "Foo { bar: 10, baz: \"Hello World\", addr: 127.0.0.1 }", + /// format!("{:?}", Foo { + /// bar: 10, + /// baz: "Hello World".to_string(), + /// addr: Ipv4Addr::new(127, 0, 0, 1), + /// }) + /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn debug_struct<'b>(&'b mut self, name: &str) -> DebugStruct<'b, 'a> { @@ -1583,20 +1604,24 @@ impl<'a> Formatter<'a> { /// /// ```rust /// use std::fmt; + /// use std::marker::PhantomData; /// - /// struct Foo(i32, String); + /// struct Foo(i32, String, PhantomData); /// - /// impl fmt::Debug for Foo { + /// impl fmt::Debug for Foo { /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { /// fmt.debug_tuple("Foo") /// .field(&self.0) /// .field(&self.1) + /// .field(&format_args!("_")) /// .finish() /// } /// } /// - /// // prints "Foo(10, "Hello World")" - /// println!("{:?}", Foo(10, "Hello World".to_string())); + /// assert_eq!( + /// "Foo(10, \"Hello\", _)", + /// format!("{:?}", Foo(10, "Hello".to_string(), PhantomData::)) + /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn debug_tuple<'b>(&'b mut self, name: &str) -> DebugTuple<'b, 'a> { @@ -1646,6 +1671,41 @@ impl<'a> Formatter<'a> { /// // prints "{10, 11}" /// println!("{:?}", Foo(vec![10, 11])); /// ``` + /// + /// [`format_args!`]: ../../std/macro.format_args.html + /// + /// In this more complex example, we use [`format_args!`] and `.debug_set()` + /// to build a list of match arms: + /// + /// ```rust + /// use std::fmt; + /// + /// struct Arm<'a, L: 'a, R: 'a>(&'a (L, R)); + /// struct Table<'a, K: 'a, V: 'a>(&'a [(K, V)], V); + /// + /// impl<'a, L, R> fmt::Debug for Arm<'a, L, R> + /// where + /// L: 'a + fmt::Debug, R: 'a + fmt::Debug + /// { + /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// L::fmt(&(self.0).0, fmt)?; + /// fmt.write_str(" => ")?; + /// R::fmt(&(self.0).1, fmt) + /// } + /// } + /// + /// impl<'a, K, V> fmt::Debug for Table<'a, K, V> + /// where + /// K: 'a + fmt::Debug, V: 'a + fmt::Debug + /// { + /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// fmt.debug_set() + /// .entries(self.0.iter().map(Arm)) + /// .entry(&Arm(&(format_args!("_"), &self.1))) + /// .finish() + /// } + /// } + /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn debug_set<'b>(&'b mut self) -> DebugSet<'b, 'a> { builders::debug_set_new(self) From afff64e7a4c88b39402c95f1368c880b17cdf793 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 21 Mar 2018 07:55:09 +0100 Subject: [PATCH 2/3] document format_args! further wrt. Debug & Display" --- src/libstd/macros.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 000f971361530..47609f17221ef 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -335,6 +335,18 @@ pub mod builtin { /// proxied through this one. `format_args!`, unlike its derived macros, avoids /// heap allocations. /// + /// You can use the [`fmt::Arguments`] value that `format_args!` returns + /// in `Debug` and `Display` contexts as seen below. The example also shows + /// that `Debug` and `Display` format to the same thing: the interpolated + /// format string in `format_args!`. + /// + /// ```rust + /// let display = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); + /// let debug = format!("{}", format_args!("{} foo {:?}", 1, 2)); + /// assert_eq!("1 foo 2", display); + /// assert_eq!(display, debug); + /// ``` + /// /// For more information, see the documentation in [`std::fmt`]. /// /// [`Display`]: ../std/fmt/trait.Display.html From 613fb8bc2c5277b9b9a14bdba3939bb6042d91ec Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 22 Mar 2018 10:06:17 +0100 Subject: [PATCH 3/3] document format_args! - fix trailing whitespace --- src/libcore/fmt/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 0363714c31b5c..62994ed15cc6d 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1682,7 +1682,7 @@ impl<'a> Formatter<'a> { /// /// struct Arm<'a, L: 'a, R: 'a>(&'a (L, R)); /// struct Table<'a, K: 'a, V: 'a>(&'a [(K, V)], V); - /// + /// /// impl<'a, L, R> fmt::Debug for Arm<'a, L, R> /// where /// L: 'a + fmt::Debug, R: 'a + fmt::Debug