Skip to content

don't drop arguments' temporaries in dbg!#154074

Merged
rust-bors[bot] merged 2 commits intorust-lang:mainfrom
dianne:dbg-temp-scopes
Mar 30, 2026
Merged

don't drop arguments' temporaries in dbg!#154074
rust-bors[bot] merged 2 commits intorust-lang:mainfrom
dianne:dbg-temp-scopes

Conversation

@dianne
Copy link
Copy Markdown
Contributor

@dianne dianne commented Mar 19, 2026

View all comments

Fixes #153850

Credit to @theemathas for help with macro engineering ^^

r? libs

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Mar 19, 2026

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Mar 19, 2026
@rustbot rustbot added the beta-nominated Nominated for backporting to the compiler in the beta channel. label Mar 19, 2026
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not totally sure where this should go. Conceptually, it makes the most sense for it to be a std test, but I can't find where dbg! is actually tested. It also only needs to pass borrowck, not be built and executed, so we could maybe save CI time by making it a //@ check-pass ui test or such.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is OK. It probably doesn't need to be an integration test though? i.e., you could add it to macros/test.rs or so?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I wasn't aware there was a difference! Done.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unit tests get compiled as part of the general crate whereas integ tests (in tests/ at the top level) each get compiled separately, so they're generally slower to compile (on a per-test amortized basis).

Comment on lines +9 to +12
*dbg!(&temp());
*dbg!(&temp(), 1).0;
*dbg!(0, &temp()).1;
*dbg!(0, &temp(), 2).1;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only the last couple of these actually regressed, but I figure we may as well be resilient to changes in dbg!.

Also, the dereferences of the temporary aren't necessary to reproduce this and weren't present in the reproducer found by crater, but I feel like being explicit makes the intent of the test clearer.

$crate::stringify!($processed),
// The `&T: Debug` check happens here (not in the format literal desugaring)
// to avoid format literal related messages and suggestions.
&&$bound as &dyn $crate::fmt::Debug
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need a double reference here? Is it to support some crazy code doing impl Debug for &Thing ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure! The double reference just coerces away as part of the cast, right? But it's been that way since #142594, so I figured I'd leave it be.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.. though on second thought, just removing the & would be a very small PR on its own, so maybe it could be bundled in here, especially if the decision is to backport a revert of #149869 instead of this.

Copy link
Copy Markdown
Contributor

@theemathas theemathas Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh. This code has compiled ever since the stabilization of dbg!() in 1.32.0.

use std::fmt::{self, Debug, Formatter};
struct Thing;
impl Debug for &Thing {
    fn fmt(&self, _: &mut Formatter) -> fmt::Result {
        Ok(())
    }
}
fn main() {
    dbg!(Thing);
}

Removing the double reference would break this code.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That feels probably accidental ^^ but it definitely shouldn't be changed as part of this, then.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dbg! macro has always done the equivalent of println!("{:?}", &x). The double reference is necessary to keep those semantics.

You can do something like

#![feature(impl_trait_in_bindings)]

fn main() {
    let x = 4_u8;
    let y: impl std::fmt::Debug = &x;
}

if you really want to get rid of the double reference/cast, though.

@rust-log-analyzer

This comment has been minimized.

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Mar 19, 2026

The Miri subtree was changed

cc @rust-lang/miri

@apiraino apiraino removed the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Mar 26, 2026
Copy link
Copy Markdown
Member

@Mark-Simulacrum Mark-Simulacrum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally this looks fine to me. I'm also not sure where (or whether they exist) there's more tests, but I think as long as you confirmed the one you added fails CI if the changes are reverted it feels OK to me.

r=me, I think it would probably make sense to revert #149869 as the beta backport but I'll leave that up to T-libs backport decision making.

View changes since this review

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is OK. It probably doesn't need to be an integration test though? i.e., you could add it to macros/test.rs or so?

| ^ value used here after move
|
help: consider borrowing instead of transferring ownership
help: consider cloning the value if the performance cost is acceptable
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like an unfortunate regression (fine for this PR but maybe file an issue for it)? It seems highly likely that borrowing is better here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently that suggestion was actually specifically meant for dbg!; I'd assumed it was generic. Maybe it's worth handling it in this PR to keep its expectation of what dbg! looks like in sync with reality—same as the clippy lint change? That test is specifically for the diagnostic too; if I'd taken care to read the linked issue (or if the test was documented or tested for the suggestion message) I'd have updated the diagnostic from the start ^^

I've added a fix, but I can move it to its own PR if that'd be better.

Comment on lines 547 to 549
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This already only worked for expansions, so I'd like to keep its scope narrow for now. If a more general "borrow here" suggestion would be helpful, I think it should be designed intentionally.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's why it only worked for expansions: self.expr_span was the move_span, which previously pointed to the match's pattern (specifically a by-move binding), which is normally separate from the match scrutinee (where dbg!'s args expand).

path @ Path { segments: [seg], .. },
)) = &arg.kind
&& seg.ident.name == self.arg_name
&& self.move_span.source_equal(arg.span)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This incidentally fixes a minor bug: if given dbg!(a, a); a;, it would produce two suggestions to borrow the second argument rather than one for each. Now that the move_span points to the user-provided argument, we can check the scrutinee for it to find the correct argument for each suggestion.

Comment on lines +572 to +575
&& e.span.macro_backtrace().any(|expn| {
expn.macro_def_id.is_some_and(|macro_def_id| {
self.tcx.is_diagnostic_item(sym::dbg_macro, macro_def_id)
})
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could avoid iterating by making dbg_internal! a diagnostic item. I figured it'd be cleaner to reuse the dbg_macro diagnostic item instead since efficiency isn't a priority, but I'm not sure.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think as-is this will also apply to e.g. dbg!(some_other_macro!(a)), right? Not sure that's desirable. But I think it's probably fairly rare that someone does that, so we can go with this for now.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so? I could be wrong, but I don't think the argument to dbg! would have the dbg! expansion in its macro backtrace, since it's not part of dbg!. I tested the spans of the moved-from arguments to dbg! in dbg-issue-120327.rs; they all have empty macro backtraces.

}

fn get_expr(_s: String) {}

// The suggestion is purely syntactic; applying it here will result in a type error.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a pre-existing issue; I consider fixing it out-of-scope. I think other suggestions to borrow often produce incorrect code, but if we want to be extra-safe, it could only fire when the dbg! invocation is on a statement of its own.

@dianne dianne added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Mar 29, 2026
@dianne
Copy link
Copy Markdown
Contributor Author

dianne commented Mar 29, 2026

Re-adding the T-compiler label since I've added in a diagnostic fix. I'll re-remove it if it'd be better as its own PR; I can add a FIXME to the diagnostic and its test in that case.

Also, it looks like my self-review notes didn't all end up rendering properly? Oops. Hopefully they still make sense.

Copy link
Copy Markdown
Member

@Mark-Simulacrum Mark-Simulacrum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors r+

I think my sense is that especially with compiler changes also involved we should land the revert on beta rather than trying to backport this.

View changes since this review

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors bot commented Mar 29, 2026

📌 Commit be31b0a has been approved by Mark-Simulacrum

It is now in the queue for this repository.

@rust-bors rust-bors bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 29, 2026
@rust-log-analyzer

This comment has been minimized.

@dianne
Copy link
Copy Markdown
Contributor Author

dianne commented Mar 29, 2026

Forgot to re-test clippy 😔 @bors r-
Easy fix, at least.

@rust-bors rust-bors bot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Mar 29, 2026
@dianne
Copy link
Copy Markdown
Contributor Author

dianne commented Mar 29, 2026

@bors r=Mark-Simulacrum

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors bot commented Mar 29, 2026

📌 Commit 7d1b41c has been approved by Mark-Simulacrum

It is now in the queue for this repository.

@rust-bors rust-bors bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 29, 2026
rust-bors bot pushed a commit that referenced this pull request Mar 29, 2026
…uwer

Rollup of 11 pull requests

Successful merges:

 - #154074 (don't drop arguments' temporaries in `dbg!`)
 - #154328 (rustdoc: add missing {os,target,target_env} values for cfg pretty printer)
 - #154540 (Fix invalid type suggestion for item nested in function)
 - #154549 (Add regression test for recursive lazy type alias normalization ICE)
 - #153373 (Fix LegacyKeyValueFormat report from docker build: powerpc)
 - #154322 (feat: reimplement `hash_map!` macro)
 - #154416 (Add `IoSplit` diagnostic item for `std::io::Split`)
 - #154486 (std_detect on AArch64 Darwin: Detect FEAT_SVE_B16B16)
 - #154508 (Fix ambiguous parsing in bootstrap.py)
 - #154518 (Panic in Hermit clock_gettime)
 - #154530 (update zulip link in `std` documentation)
@rust-bors rust-bors bot merged commit 2a18b88 into rust-lang:main Mar 30, 2026
11 checks passed
rust-timer added a commit that referenced this pull request Mar 30, 2026
Rollup merge of #154074 - dianne:dbg-temp-scopes, r=Mark-Simulacrum

don't drop arguments' temporaries in `dbg!`

Fixes #153850

Credit to @theemathas for help with macro engineering ^^

r? libs
github-actions bot pushed a commit to rust-lang/miri that referenced this pull request Mar 30, 2026
…uwer

Rollup of 11 pull requests

Successful merges:

 - rust-lang/rust#154074 (don't drop arguments' temporaries in `dbg!`)
 - rust-lang/rust#154328 (rustdoc: add missing {os,target,target_env} values for cfg pretty printer)
 - rust-lang/rust#154540 (Fix invalid type suggestion for item nested in function)
 - rust-lang/rust#154549 (Add regression test for recursive lazy type alias normalization ICE)
 - rust-lang/rust#153373 (Fix LegacyKeyValueFormat report from docker build: powerpc)
 - rust-lang/rust#154322 (feat: reimplement `hash_map!` macro)
 - rust-lang/rust#154416 (Add `IoSplit` diagnostic item for `std::io::Split`)
 - rust-lang/rust#154486 (std_detect on AArch64 Darwin: Detect FEAT_SVE_B16B16)
 - rust-lang/rust#154508 (Fix ambiguous parsing in bootstrap.py)
 - rust-lang/rust#154518 (Panic in Hermit clock_gettime)
 - rust-lang/rust#154530 (update zulip link in `std` documentation)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

beta-nominated Nominated for backporting to the compiler in the beta channel. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1.95 beta regression: "temporary value dropped while borrowed"

7 participants