Does Rust have a debug macro?

Rust 1.32.0

Rust 1.32.0 stabilized the dbg!() macro, which outputs:

  • The file name on which the macro was called.
  • The line number on which the macro was called.
  • A pretty print of the argument (which must implement the Debug trait).

Note: dbg!() moves its argument, so you may want to pass non-copy types by reference.

Example: Array of Points (Playground)

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let points = [
        Point { x: 0, y: 0 },
        Point { x: 2, y: 3 },
        Point { x: 5, y: 7 },
    ];

    dbg!(&points);
}

Program Output

[src/main.rs:14] &points = [
    Point {
        x: 0,
        y: 0
    },
    Point {
        x: 2,
        y: 3
    },
    Point {
        x: 5,
        y: 7
    }
]

Example: Conditional Compilation (Playground)

The OP expressed a desire to display the debug content only when compiling in debug mode.

The following is a way to achieve this:

#[cfg(debug_assertions)]
macro_rules! debug {
    ($x:expr) => { dbg!($x) }
}

#[cfg(not(debug_assertions))]
macro_rules! debug {
    ($x:expr) => { std::convert::identity($x) }
}

fn main() {
    let x = 4;
    debug!(x);
    if debug!(x == 5) {
        println!("x == 5");
    } else {
        println!("x != 5");
    }
}

Program Output (Debug Mode)

---------------------Standard Error-----------------------

[src/main.rs:13] x = 4
[src/main.rs:14] x == 5 = false

---------------------Standard Output----------------------

x != 5

Program Output (Release Mode)

---------------------Standard Output----------------------

x != 5

Before Rust 1.32.0

You could use the log crate or you could define one yourself.


Although it makes sense to use something like the log crate as mentioned in DK's answer, here's how to do the direct equivalent of what you asked:

// The debug version
#[cfg(feature = "my_debug")]
macro_rules! debug_print {
    ($( $args:expr ),*) => { println!( $( $args ),* ); }
}

// Non-debug version
#[cfg(not(feature = "my_debug"))]
macro_rules! debug_print {
    ($( $args:expr ),*) => {}
}

fn main() {
    debug_print!("Debug only {}", 123);
}

And in your Cargo.toml, add a [features] section:

[features]
my_debug = []

The output then appears with cargo run --features my_debug, and doesn't with a plain cargo run.


You could define them yourself, but it would be simpler to use the log crate, which defines several macros for various purposes (see the log documentation).

Note that the crate only provides the frontend for logging; you'll also need to select a backend. There's a basic example in the log documentation, or you could use something like env_logger or log4rs.


Macro based on Chris Emerson answer and CJ McAllister comment

// Disable warnings

#[allow(unused_macros)]

// The debug version

#[cfg(debug_assertions)]
macro_rules! log {
    ($( $args:expr ),*) => { println!( $( $args ),* ); }
}

// Non-debug version

#[cfg(not(debug_assertions))]
macro_rules! log {
    ($( $args:expr ),*) => {()}
}

Using

log!("Don't be crazy");
log!("Answer is {}", 42);

Building by cargo build --release will replace all log!(...) with unit tuple ();

I didn't found the way to replace to nothing but I think compiler will do it.