rust-lang / rust-lang/rust

`dbg!()` only requires `&T` (not `T`) to implement `Debug`.

Open
#154,589 0 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-fmt C-discussion T-libs
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

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 https://github.com/rust-lang/rust/pull/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 https://github.com/rust-lang/rust/pull/154074#discussion_r2957799638, 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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with library/std/src/macros.rs and the regression test tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-ref-impl.rs, then read RFC 2361's reference-level explanation. Determine whether the reference-level Debug behavior should remain or change, and capture the decision with appropriate test or documentation updates.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.