In Rust, Debug is a trait that allows us to inspect the state of a struct by printing the struct to std out or, you know, whatever. Usually, we just derive debug implementations, but there are cases when that's not possible or even desirable. Here's a real world example.

pub struct Collector {
    lexer: Lexer,
    sections: Vec<(Option<String>, Stats)>,
    total_words: u32,
    heading_width: usize,
}

This Collector presents four fields, two of which are already compatible with a derived Debug implementation. Provided that Stats is also derive-compatible (and that it is so derived), we have three out of four. The same can be said of Lexer, but I can tell you right now that Lexer has no meaningful debug derivation. So, what do we do?

Option A may be to just implement Debug the way we would implement Display—a hand-coded format that looks exactly the way we want. Thing is, the standard debug format is actually pretty complicated, and it'll be obvious if we don't follow it to the letter. If we don't want our implementation to stand out as "off" somehow, we'll need to put in non-trivial effort. That's no fun, is it?

Option B involves the use of a "debug helper struct" built into the formatting subsystem. Observe!

impl fmt::Debug for Collector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut d = f.debug_struct("Collector");
        d.field("sections", &self.sections);
        d.field("total_words", &self.total_words);
        d.field("heading_width", &self.heading_width);
        d.finish()
    }
}

Pretty cool, huh? This spits out a debug format that is mostly indistinguishable from the "real" thing, except for the obvious fact that we totally skipped the lexer field. Woot!