This issue is to document a weirdness with the dbg!() macro, and possibly maybe decide if we want to change this behavior.
The following code compiles:
use std::fmt::{self, Debug, Formatter};
struct Thing;
// implemented on a reference
impl Debug for &Thing {
fn fmt(&self, _: &mut Formatter) -> fmt::Result {
Ok(())
}
}
fn main() {
dbg!(Thing);
}
Note that if we were to instead write println!("{:?}", Thing), then the code would not compile, since that syntax would require Thing to implement Debug.
This weirdness existed from the beginning, in RFC 2361, which contains example code with eprintln!(...., &expr). This reference is redundant, since eprintln already adds a reference, but this seemingly went unnoticed. Thus, this causes a value of type &&Thing (with a double reference) to be turned into the type &dyn Debug. The double reference seems a bit wasteful to me.
The weirdness was noticed in #142594, and so a test was added to ensure that this didn't accidentally break. Note that, after this PR, the code now explicitly creates a &&Thing, then explicitly coerces that to &dyn Debug. Then, a reference to that is creating, making a &&dyn Debug, which is then again coerced to &dyn Debug. This in total results in a triple reference to the actual value.
This weirdness was rediscovered in #154074 (comment), where the weirdness is preserved as-is.
Meta
Reproducible on the playground with version 1.96.0-nightly (2026-03-29 a25435bcf7cfc9b953d3), but the weirdness has existed since the stabilization of dbg!() in 1.32.0.
This issue is to document a weirdness with the
dbg!()macro, and possibly maybe decide if we want to change this behavior.The following code compiles:
Note that if we were to instead write
println!("{:?}", Thing), then the code would not compile, since that syntax would requireThingto implementDebug.This weirdness existed from the beginning, in RFC 2361, which contains example code with
eprintln!(...., &expr). This reference is redundant, sinceeprintlnalready adds a reference, but this seemingly went unnoticed. Thus, this causes a value of type&&Thing(with a double reference) to be turned into the type&dyn Debug. The double reference seems a bit wasteful to me.The weirdness was noticed in #142594, and so a test was added to ensure that this didn't accidentally break. Note that, after this PR, the code now explicitly creates a
&&Thing, then explicitly coerces that to&dyn Debug. Then, a reference to that is creating, making a&&dyn Debug, which is then again coerced to&dyn Debug. This in total results in a triple reference to the actual value.This weirdness was rediscovered in #154074 (comment), where the weirdness is preserved as-is.
Meta
Reproducible on the playground with version
1.96.0-nightly (2026-03-29 a25435bcf7cfc9b953d3), but the weirdness has existed since the stabilization ofdbg!()in 1.32.0.