🎓 A1Learner
🔍

Rust Debug Printing

Debug printing is the programmer's view of a value, with every field shown exactly as stored. Deriving Debug gives a struct the `{:?}` form instead.

A struct will not print with {}

Rust will not guess how your struct should look. Derive Debug instead, and print with {:?}:

#[derive(Debug)]
struct Rectangle { width: u32, height: u32 }
let rect = Rectangle { width: 60, height: 50 };
// println!("{}", rect); // error: a struct has no Display form of its own
println!("{:?}", rect);

Pretty Debug with {:#?}

Add a # inside the braces. Each field gets its own line. That form wins when a struct grows large:

let rect = Rectangle { width: 60, height: 50 };
println!("{:#?}", rect);

A quick peek with dbg!

While fixing bugs, dbg! prints the file, the line and the value to the error output, and hands the value back. The output below is what the ordinary printing shows:

let rect = Rectangle { width: 60, height: 50 };
let rect = dbg!(rect);
println!("still usable: {} x {}", rect.width, rect.height);

dbg! inside a working-out

dbg! can wrap a sum, too. It reports the sum and its result on the error output. The field still gets the result:

let rect = Rectangle { width: dbg!(30 * 2), height: 50 };
println!("width = {}", rect.width);

Debug on the inside, too

A struct that holds another struct needs Debug on both. Deriving Debug on the outer struct fails with error E0277 if the inner one has none:

#[derive(Debug)]
struct Point { x: i32, y: i32 }
#[derive(Debug)]
struct Rectangle { top_left: Point, bottom_right: Point }
let rect = Rectangle { top_left: Point { x: 1, y: 4 }, bottom_right: Point { x: 5, y: 1 } };
println!("{:?}", rect);

Example

#[derive(Debug)]
struct Rectangle { width: u32, height: u32 }
fn main() {
    let rect = Rectangle { width: 60, height: 50 };
    println!("rect is {:#?}", rect);
    println!("one line: {:?}", rect);
}

Key points

  • Debug printing shows a value as the programmer needs it: every field, exactly as stored.
  • Derived Debug always shows the type name and the stored values exactly as they are.
  • The programmer gets no say in the look.
  • Choosing the look is what Display is for.
  • Numbers and words print with println! and {}.
  • Structs get Debug from derive.
  • Display comes only later, when the programmer writes it.

In this example, rect is a Rectangle with width 60 and height 50. The #[derive(Debug)] line above the struct gives Rectangle its Debug form. The first println! uses {:#?}, the pretty form, so each field gets its own line. The second println! uses {:?} and prints the same value on one line: Rectangle { width: 60, height: 50 }. Same value, two views — the pretty one wins when a struct grows large.

Note

{} is Display, the tidy form for end users.

{:?} is Debug, the detailed form for the programmer.

Numbers have both forms.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

Which format prints a struct in the pretty Debug form, one field per line?