Skip to content

Debug vs Display in Rust

Display and Debug both format values, but they make different promises. Display is a deliberate user-facing representation. Debug is for programmer-facing inspection and diagnostics.

EXAMPLE: CI-CHECKEDTEST ASSERTED · examples/format-output/src/display_page.rs#debug-display-contrast
impl fmt::Display for LabelledPoint {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "{},{}", self.x, self.y)
    }
}

Display powers {}. It cannot be derived because the standard library cannot decide what the one intended user-facing representation of an arbitrary type should be.

Implementing Display also gives the type the blanket ToString implementation, so implement Display rather than implementing ToString directly.

Typical uses include text shown to users, concise human-readable identifiers, and labels where the representation is part of the type’s public behavior.

Debug powers {:?}. For ordinary structs and enums, #[derive(Debug)] is usually the right starting point.

Its purpose is inspection, so exposing field names and internal structure is normal. That also means it should not be treated as a stable wire format or serialization contract.

There is no conflict in implementing both traits with different representations. That is often the useful design.

The Display output can stay concise while Debug shows enough internal state to diagnose a problem. Code then chooses intentionally between {value} and {value:?} instead of trying to make one representation serve every audience.

For the full mapping between format suffixes and traits, see formatting traits.