Show value only in debug mode

dbg! shows output both in debug and release builds. Is there a variant (without needing an external crate preferably) which doesn't do it in the release build? This is so that the dbg! statement doesn't have to be removed everytime the code is finalized.

macro_rules! debug {
    ($($e:expr),+) => {
        {
            #[cfg(debug_assertions)]
            {
                dbg!($($e),+)
            }
            #[cfg(not(debug_assertions))]
            {
                ($($e),+)
            }
        }
    };
}

let x: (usize, &str) = debug!(2, "abc");
//Prints in debug:
// [src/main.rs:17] 2 = 2
// [src/main.rs:17] "abc" = "abc"
//Doesn't print anything in release.

Playground

This macro will do what you're asking for. dbg is really meant to be a debugging tool, and is meant to be a nicer println!, so it should be removed. However, this will remove it when you're compiling on release mode.

1 Like

Thanks to you, I came to know about cfg(debug_assertions).

Something like the following serves the purpose for now. I am fine with having to repeat the attribute.

#[cfg(debug_assertions)] dbg!(x,y,z);

I wonder why dbg! wasn't designed to do this in the first place.

The dbg! macro is intended for quick debugging where you throw in some prints and then remove them afterwards. If you want a logging system where you can turn some of the logging off, get a proper logging system.

You can re declare it with some modifications then:

macro_rules! dbg {
    ($($x:tt)*) => {
        {
            #[cfg(debug_assertions)]
            {
                std::dbg!($($x)*)
            }
            #[cfg(not(debug_assertions))]
            {
                ($($x)*)
            }
        }
    }
}

fn main() {
    dbg!(1, 2, 3);
}

Playground


Edited to correct for typo.

1 Like

What's the difference between the arguments exactly?

That this is a drop-in replacement. It's called dbg and shadows the std::dbg.


Technically it isn't a complete drop in, since the following two don't result in the same type on release mode: dbg!(1,) and std::dbg!(1,). Playground.

No, the difference between ($($e:expr),+) and ($($x)*).

Oh!

$($e:expr),+)

Matches one or more expressions separated by commas.
Examples:

1
4, 5
{}, ()
"abc", String::new()
<A as Add<B>>::Output::SomeConst

While

$($x:tt)*

Matches everything.

$x:tt

Matches a token tree. The following are valid token trees:

a
@
#
String
::
new
()
{ text }

So, if we repeat it for zero or more times (That's what * at the end does), then we can match anything. I then push it into the dbg! macro, therefore copying the input verbatim, or put it into a tuple.

The difference in small text in my previous post comes from the fact that std::dbg matches on $e:expr, and allows a trailing comma (either with a new case, or with $(,)? which matches zero or one ,). So, if we just put the input verbatim into the parenthesis to make a tuple, we may end up with a 1-tuple in the case we have a trailing comma in the input, while the std::dbg macro would have returned the value.

1 Like

Thank you. I'll use your answer for future reference.

1 Like

Because it is in some cases useful (or even necessary) to debug stuff in release mode.

True, I just feel that dbg is a poor word of choice.

The word debug may be a bit overloaded here, but I think that dbg! is a good name for the macro nonetheless.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.