Display and Debug Traits
Display and Debug teach your type two different ways to turn itself into readable text: one polished for people, one detailed for developers.In this page:
use std::fmt;
impl fmt::Display for Name {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.field)
}
}
#[derive(Debug)]
Deriving Debug
#[derive(Debug)] automatically generates a Debug implementation, letting a struct be printed with {:?} for quick developer-facing inspection.
Example: Deriving Debug
// Auto-generate #[derive(Debug)] for the type below
#[derive(Debug)]
// Define a struct `Point` to group related fields together
struct Point {
x: i32,
y: i32,
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `p`, set to `Point { x: 1, y: 2 }`
let p = Point { x: 1, y: 2 };
// Print "{:?}" to the console, substituting in `p` (with a trailing newline)
println!("{:?}", p);
}
Login to try C/C++/Java/PHP code in the editor
Implementing Display Manually
Display has no automatic derive and must be implemented by hand, defining exactly how the type should look in clean, user-facing output via {}.
Example: Implementing Display Manually
// Bring `std::fmt` into scope
use std::fmt;
// Define a struct `Point` to group related fields together
struct Point {
x: i32,
y: i32,
}
// Implement methods on `fmt`
impl fmt::Display for Point {
// Define the function `fmt` taking `&self`, `f` and returning a `fmt::Result`
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `p`, set to `Point { x: 3, y: 4 }`
let p = Point { x: 3, y: 4 };
// Print "{}" to the console, substituting in `p` (with a trailing newline)
println!("{}", p);
}
Login to try C/C++/Java/PHP code in the editor
Implementing Both Traits on the Same Type
A type can implement both Display and Debug at once, giving it two distinct textual representations depending on whether {} or {:?} is used.
Example: Implementing Both Traits on the Same Type
// Bring `std::fmt` into scope
use std::fmt;
// Auto-generate #[derive(Debug)] for the type below
#[derive(Debug)]
// Define a struct `Money` to group related fields together
struct Money {
cents: i64,
}
// Implement methods on `fmt`
impl fmt::Display for Money {
// Define the function `fmt` taking `&self`, `f` and returning a `fmt::Result`
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "${:.2}", self.cents as f64 / 100.0)
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `price`, set to `Money { cents: 1999 }`
let price = Money { cents: 1999 };
// Print "Display: {}" to the console, substituting in `price` (with a trailing newline)
println!("Display: {}", price);
// Print "Debug: {:?}" to the console, substituting in `price` (with a trailing newline)
println!("Debug: {:?}", price);
}
Login to try C/C++/Java/PHP code in the editor
Using write! Inside fmt
The write! macro is how both Display and Debug implementations produce their output, writing formatted text into the provided Formatter and returning a fmt::Result.
Example: Using write! Inside fmt
// Bring `std::fmt` into scope
use std::fmt;
// Define a struct `Temperature` to group related fields together
struct Temperature(f64);
// Implement methods on `fmt`
impl fmt::Display for Temperature {
// Define the function `fmt` taking `&self`, `f` and returning a `fmt::Result`
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:.1} degrees", self.0)
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `t`, set to `Temperature(23.456)`
let t = Temperature(23.456);
// Print "{}" to the console, substituting in `t` (with a trailing newline)
println!("{}", t);
}
Login to try C/C++/Java/PHP code in the editor
- Trying to derive
Displaywith#[derive(Display)]-- unlikeDebug,Displayhas no built-in derive and must be implemented manually. - Implementing
Displaybut forgettingDebugis still needed separately for{:?}formatting to work. - Returning a
Stringdirectly fromfmtinstead of usingwrite!(f, ...), which is the correct way to produce Display/Debug output.
Display({}) must be implemented manually and is meant for clean, user-facing output.Debug({:?}) can be auto-derived with#[derive(Debug)]and is meant for developer-facing diagnostics.- Both traits are implemented by defining an
fmtmethod that writes into aFormatterusing thewrite!macro. - A type can implement both traits simultaneously, providing different output for
{}versus{:?}.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: