don't leak internal temporaries from dbg!

(cherry picked from commit 35be9f2208)
This commit is contained in:
dianne
2026-04-08 08:42:07 -07:00
committed by Josh Stone
parent 216757db18
commit b4d644b3b6
2 changed files with 29 additions and 2 deletions
+5 -2
View File
@@ -369,7 +369,8 @@ macro_rules! dbg {
/// E.g. `dbg_internal!(() () (1, 2))` expands into
/// ```rust, ignore
/// match (1, 2) {
/// (tmp_1, tmp_2) => {
/// args => {
/// let (tmp_1, tmp_2) = args;
/// eprint!("...", &tmp_1, &tmp_2, /* some other arguments */);
/// (tmp_1, tmp_2)
/// }
@@ -385,7 +386,9 @@ macro_rules! dbg {
// of temporaries - https://stackoverflow.com/a/48732525/1063961
// Always put the arguments in a tuple to avoid an unused parens lint on the pattern.
match ($($processed,)+) {
($($bound,)+) => {
// Move the entire tuple so it doesn't stick around as a temporary (#154988).
args => {
let ($($bound,)+) = args;
$crate::eprint!(
$crate::concat!($($piece),+),
$(
+24
View File
@@ -1,5 +1,7 @@
// ignore-tidy-dbg
use core::fmt::Debug;
/// Test for <https://github.com/rust-lang/rust/issues/153850>:
/// `dbg!` shouldn't drop arguments' temporaries.
#[test]
@@ -11,3 +13,25 @@ fn temp() {}
*dbg!(0, &temp()).1;
*dbg!(0, &temp(), 2).1;
}
/// Test for <https://github.com/rust-lang/rust/issues/154988>:
/// `dbg!` shouldn't create a temporary that lives past its invocation.
#[test]
fn no_leaking_internal_temps_from_dbg() {
#[derive(Debug)]
struct Foo;
#[derive(Debug)]
struct Bar<'a>(#[allow(unused)] &'a Foo);
impl Drop for Bar<'_> {
fn drop(&mut self) {}
}
let foo = Foo;
let bar = Bar(&foo);
// If `dbg!` creates a `(Bar<'_>,)` temporary that lasts past its expansion, this will fail
// to compile, because it will be dropped after `foo`, which it borrows from. The tuple
// mimics the drop order of block tail expressions before Rust 2024: first the result of `dbg!`
// is dropped, then `foo`, then any temporaries left over from `dbg!` are dropped, if present.
(drop(dbg!(bar)), drop(foo));
}