mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-26 13:01:27 +03:00
don't leak internal temporaries from dbg!
(cherry picked from commit 35be9f2208)
This commit is contained in:
@@ -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),+),
|
||||
$(
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user