From bad8e98c7d0ed217b58362e61ae4357e5344d995 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 23 Feb 2025 01:09:51 +0000 Subject: [PATCH] Consider lvalues of field and index as possibly temporary places --- compiler/rustc_lint/src/if_let_rescope.rs | 8 +++++++ .../lint-if-let-rescope-false-positives.rs | 4 ++++ tests/ui/drop/lint-if-let-rescope.fixed | 6 +++++ tests/ui/drop/lint-if-let-rescope.rs | 6 +++++ tests/ui/drop/lint-if-let-rescope.stderr | 23 ++++++++++++++++++- 5 files changed, 46 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 55d900e031990..23f037f3692ab 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -436,6 +436,14 @@ impl<'tcx> Visitor<'tcx> for FindSignificantDropper<'_, 'tcx> { self.check_promoted_temp_with_drop(expr)?; intravisit::walk_expr(self, expr) } + // `(Drop, ()).1` introduces a temporary and then moves out of + // part of it, therefore we should check it for temporaries. + // FIXME: This may have false positives if we move the part + // that actually has drop, but oh well. + hir::ExprKind::Index(expr, _, _) | hir::ExprKind::Field(expr, _) => { + self.check_promoted_temp_with_drop(expr)?; + intravisit::walk_expr(self, expr) + } // If always introduces a temporary terminating scope for its cond and arms, // so don't visit them. hir::ExprKind::If(..) => ControlFlow::Continue(()), diff --git a/tests/ui/drop/lint-if-let-rescope-false-positives.rs b/tests/ui/drop/lint-if-let-rescope-false-positives.rs index 533d0f2f982b3..77b7df4bc3bab 100644 --- a/tests/ui/drop/lint-if-let-rescope-false-positives.rs +++ b/tests/ui/drop/lint-if-let-rescope-false-positives.rs @@ -26,4 +26,8 @@ fn main() { // Make sure we don't lint if we consume the droppy value. if let None = consume(Drop) {} else {} + + // Make sure we don't lint on field exprs of place exprs. + let tup_place = (Drop, ()); + if let None = consume(tup_place.1) {} else {} } diff --git a/tests/ui/drop/lint-if-let-rescope.fixed b/tests/ui/drop/lint-if-let-rescope.fixed index 182190aa323bc..79858e6f225aa 100644 --- a/tests/ui/drop/lint-if-let-rescope.fixed +++ b/tests/ui/drop/lint-if-let-rescope.fixed @@ -94,6 +94,12 @@ fn main() { //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 } + match Some((droppy(), ()).1) { Some(_value) => {} _ => {}} + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: the value is now dropped here in Edition 2024 + //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 + // We want to keep the `if let`s below as direct descendents of match arms, // so the formatting is suppressed. #[rustfmt::skip] diff --git a/tests/ui/drop/lint-if-let-rescope.rs b/tests/ui/drop/lint-if-let-rescope.rs index e1b38be0a0f50..9d873c65426f6 100644 --- a/tests/ui/drop/lint-if-let-rescope.rs +++ b/tests/ui/drop/lint-if-let-rescope.rs @@ -94,6 +94,12 @@ fn main() { //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 } + if let Some(_value) = Some((droppy(), ()).1) {} else {} + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: the value is now dropped here in Edition 2024 + //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 + // We want to keep the `if let`s below as direct descendents of match arms, // so the formatting is suppressed. #[rustfmt::skip] diff --git a/tests/ui/drop/lint-if-let-rescope.stderr b/tests/ui/drop/lint-if-let-rescope.stderr index 2b0fcb7a938a6..b17239976cc0d 100644 --- a/tests/ui/drop/lint-if-let-rescope.stderr +++ b/tests/ui/drop/lint-if-let-rescope.stderr @@ -175,5 +175,26 @@ LL - while (if let Some(_value) = droppy().get() { false } else { true }) { LL + while (match droppy().get() { Some(_value) => { false } _ => { true }}) { | -error: aborting due to 7 previous errors +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope.rs:97:8 + | +LL | if let Some(_value) = Some((droppy(), ()).1) {} else {} + | ^^^^^^^^^^^^^^^^^^^^^^^^--------------^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope.rs:97:51 + | +LL | if let Some(_value) = Some((droppy(), ()).1) {} else {} + | ^ +help: a `match` with a single arm can preserve the drop order up to Edition 2021 + | +LL - if let Some(_value) = Some((droppy(), ()).1) {} else {} +LL + match Some((droppy(), ()).1) { Some(_value) => {} _ => {}} + | + +error: aborting due to 8 previous errors