Skip to content

Commit 59b36a5

Browse files
Rollup merge of rust-lang#154994 - dianne:no-dbg-temp, r=Mark-Simulacrum
don't leak internal temporaries from `dbg!` Fixes rust-lang#154988 r? @Mark-Simulacrum as the reviewer of rust-lang#154074
2 parents 197eb8c + 35be9f2 commit 59b36a5

2 files changed

Lines changed: 29 additions & 2 deletions

File tree

library/std/src/macros.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,8 @@ macro_rules! dbg {
369369
/// E.g. `dbg_internal!(() () (1, 2))` expands into
370370
/// ```rust, ignore
371371
/// match (1, 2) {
372-
/// (tmp_1, tmp_2) => {
372+
/// args => {
373+
/// let (tmp_1, tmp_2) = args;
373374
/// eprint!("...", &tmp_1, &tmp_2, /* some other arguments */);
374375
/// (tmp_1, tmp_2)
375376
/// }
@@ -385,7 +386,9 @@ pub macro dbg_internal {
385386
// of temporaries - https://stackoverflow.com/a/48732525/1063961
386387
// Always put the arguments in a tuple to avoid an unused parens lint on the pattern.
387388
match ($($processed,)+) {
388-
($($bound,)+) => {
389+
// Move the entire tuple so it doesn't stick around as a temporary (#154988).
390+
args => {
391+
let ($($bound,)+) = args;
389392
$crate::eprint!(
390393
$crate::concat!($($piece),+),
391394
$(

library/std/src/macros/tests.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// ignore-tidy-dbg
22

3+
use core::fmt::Debug;
4+
35
/// Test for <https://github.com/rust-lang/rust/issues/153850>:
46
/// `dbg!` shouldn't drop arguments' temporaries.
57
#[test]
@@ -11,3 +13,25 @@ fn no_dropping_temps() {
1113
*dbg!(0, &temp()).1;
1214
*dbg!(0, &temp(), 2).1;
1315
}
16+
17+
/// Test for <https://github.com/rust-lang/rust/issues/154988>:
18+
/// `dbg!` shouldn't create a temporary that lives past its invocation.
19+
#[test]
20+
fn no_leaking_internal_temps_from_dbg() {
21+
#[derive(Debug)]
22+
struct Foo;
23+
24+
#[derive(Debug)]
25+
struct Bar<'a>(#[allow(unused)] &'a Foo);
26+
impl Drop for Bar<'_> {
27+
fn drop(&mut self) {}
28+
}
29+
30+
let foo = Foo;
31+
let bar = Bar(&foo);
32+
// If `dbg!` creates a `(Bar<'_>,)` temporary that lasts past its expansion, this will fail
33+
// to compile, because it will be dropped after `foo`, which it borrows from. The tuple
34+
// mimics the drop order of block tail expressions before Rust 2024: first the result of `dbg!`
35+
// is dropped, then `foo`, then any temporaries left over from `dbg!` are dropped, if present.
36+
(drop(dbg!(bar)), drop(foo));
37+
}

0 commit comments

Comments
 (0)