Skip to content

Commit 175595a

Browse files
committed
Rollup merge of rust-lang#49229 - Centril:doc/format_args_display_debug, r=steveklabnik
Document format_args! / Arguments<'a> behavior wrt. Display and Debug This is a follow up PR to rust-lang#49067 , this documents the behavior of `format_args!` (i.e: `Argument<'a>`) wrt. `Display` and `Debug`.
2 parents 85abb05 + 613fb8b commit 175595a

File tree

2 files changed

+78
-6
lines changed

2 files changed

+78
-6
lines changed

src/libcore/fmt/mod.rs

+66-6
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,18 @@ impl<'a> Arguments<'a> {
406406
/// macro validates the format string at compile-time so usage of the [`write`]
407407
/// and [`format`] functions can be safely performed.
408408
///
409+
/// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug`
410+
/// and `Display` contexts as seen below. The example also shows that `Debug`
411+
/// and `Display` format to the same thing: the interpolated format string
412+
/// in `format_args!`.
413+
///
414+
/// ```rust
415+
/// let display = format!("{:?}", format_args!("{} foo {:?}", 1, 2));
416+
/// let debug = format!("{}", format_args!("{} foo {:?}", 1, 2));
417+
/// assert_eq!("1 foo 2", display);
418+
/// assert_eq!(display, debug);
419+
/// ```
420+
///
409421
/// [`format_args!`]: ../../std/macro.format_args.html
410422
/// [`format`]: ../../std/fmt/fn.format.html
411423
/// [`write`]: ../../std/fmt/fn.write.html
@@ -1553,23 +1565,32 @@ impl<'a> Formatter<'a> {
15531565
///
15541566
/// ```rust
15551567
/// use std::fmt;
1568+
/// use std::net::Ipv4Addr;
15561569
///
15571570
/// struct Foo {
15581571
/// bar: i32,
15591572
/// baz: String,
1573+
/// addr: Ipv4Addr,
15601574
/// }
15611575
///
15621576
/// impl fmt::Debug for Foo {
15631577
/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
15641578
/// fmt.debug_struct("Foo")
15651579
/// .field("bar", &self.bar)
15661580
/// .field("baz", &self.baz)
1581+
/// .field("addr", &format_args!("{}", self.addr))
15671582
/// .finish()
15681583
/// }
15691584
/// }
15701585
///
1571-
/// // prints "Foo { bar: 10, baz: "Hello World" }"
1572-
/// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() });
1586+
/// assert_eq!(
1587+
/// "Foo { bar: 10, baz: \"Hello World\", addr: 127.0.0.1 }",
1588+
/// format!("{:?}", Foo {
1589+
/// bar: 10,
1590+
/// baz: "Hello World".to_string(),
1591+
/// addr: Ipv4Addr::new(127, 0, 0, 1),
1592+
/// })
1593+
/// );
15731594
/// ```
15741595
#[stable(feature = "debug_builders", since = "1.2.0")]
15751596
pub fn debug_struct<'b>(&'b mut self, name: &str) -> DebugStruct<'b, 'a> {
@@ -1583,20 +1604,24 @@ impl<'a> Formatter<'a> {
15831604
///
15841605
/// ```rust
15851606
/// use std::fmt;
1607+
/// use std::marker::PhantomData;
15861608
///
1587-
/// struct Foo(i32, String);
1609+
/// struct Foo<T>(i32, String, PhantomData<T>);
15881610
///
1589-
/// impl fmt::Debug for Foo {
1611+
/// impl<T> fmt::Debug for Foo<T> {
15901612
/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
15911613
/// fmt.debug_tuple("Foo")
15921614
/// .field(&self.0)
15931615
/// .field(&self.1)
1616+
/// .field(&format_args!("_"))
15941617
/// .finish()
15951618
/// }
15961619
/// }
15971620
///
1598-
/// // prints "Foo(10, "Hello World")"
1599-
/// println!("{:?}", Foo(10, "Hello World".to_string()));
1621+
/// assert_eq!(
1622+
/// "Foo(10, \"Hello\", _)",
1623+
/// format!("{:?}", Foo(10, "Hello".to_string(), PhantomData::<u8>))
1624+
/// );
16001625
/// ```
16011626
#[stable(feature = "debug_builders", since = "1.2.0")]
16021627
pub fn debug_tuple<'b>(&'b mut self, name: &str) -> DebugTuple<'b, 'a> {
@@ -1646,6 +1671,41 @@ impl<'a> Formatter<'a> {
16461671
/// // prints "{10, 11}"
16471672
/// println!("{:?}", Foo(vec![10, 11]));
16481673
/// ```
1674+
///
1675+
/// [`format_args!`]: ../../std/macro.format_args.html
1676+
///
1677+
/// In this more complex example, we use [`format_args!`] and `.debug_set()`
1678+
/// to build a list of match arms:
1679+
///
1680+
/// ```rust
1681+
/// use std::fmt;
1682+
///
1683+
/// struct Arm<'a, L: 'a, R: 'a>(&'a (L, R));
1684+
/// struct Table<'a, K: 'a, V: 'a>(&'a [(K, V)], V);
1685+
///
1686+
/// impl<'a, L, R> fmt::Debug for Arm<'a, L, R>
1687+
/// where
1688+
/// L: 'a + fmt::Debug, R: 'a + fmt::Debug
1689+
/// {
1690+
/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1691+
/// L::fmt(&(self.0).0, fmt)?;
1692+
/// fmt.write_str(" => ")?;
1693+
/// R::fmt(&(self.0).1, fmt)
1694+
/// }
1695+
/// }
1696+
///
1697+
/// impl<'a, K, V> fmt::Debug for Table<'a, K, V>
1698+
/// where
1699+
/// K: 'a + fmt::Debug, V: 'a + fmt::Debug
1700+
/// {
1701+
/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1702+
/// fmt.debug_set()
1703+
/// .entries(self.0.iter().map(Arm))
1704+
/// .entry(&Arm(&(format_args!("_"), &self.1)))
1705+
/// .finish()
1706+
/// }
1707+
/// }
1708+
/// ```
16491709
#[stable(feature = "debug_builders", since = "1.2.0")]
16501710
pub fn debug_set<'b>(&'b mut self) -> DebugSet<'b, 'a> {
16511711
builders::debug_set_new(self)

src/libstd/macros.rs

+12
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,18 @@ pub mod builtin {
335335
/// proxied through this one. `format_args!`, unlike its derived macros, avoids
336336
/// heap allocations.
337337
///
338+
/// You can use the [`fmt::Arguments`] value that `format_args!` returns
339+
/// in `Debug` and `Display` contexts as seen below. The example also shows
340+
/// that `Debug` and `Display` format to the same thing: the interpolated
341+
/// format string in `format_args!`.
342+
///
343+
/// ```rust
344+
/// let display = format!("{:?}", format_args!("{} foo {:?}", 1, 2));
345+
/// let debug = format!("{}", format_args!("{} foo {:?}", 1, 2));
346+
/// assert_eq!("1 foo 2", display);
347+
/// assert_eq!(display, debug);
348+
/// ```
349+
///
338350
/// For more information, see the documentation in [`std::fmt`].
339351
///
340352
/// [`Display`]: ../std/fmt/trait.Display.html

0 commit comments

Comments
 (0)