rust/tests/ui/nll/issue-54556-niconii.rs
Ding Xiang Fei f93df1f7dc
rescope temp lifetime in let-chain into IfElse
apply rules by span edition
2024-09-11 04:10:00 +08:00

49 lines
1.7 KiB
Rust

// This is a reduction of a concrete test illustrating a case that was
// annoying to Rust developer niconii (see comment thread on #21114).
//
// With resolving issue #54556, pnkfelix hopes that the new diagnostic
// output produced by NLL helps to *explain* the semantic significance
// of temp drop order, and thus why inserting a semi-colon after the
// `if let` expression in `main` works.
//@ revisions: edition2021 edition2024
//@ [edition2021] edition: 2021
//@ [edition2024] edition: 2024
//@ [edition2024] compile-flags: -Z unstable-options
//@ [edition2024] check-pass
#![cfg_attr(edition2024, feature(if_let_rescope))]
struct Mutex;
struct MutexGuard<'a>(&'a Mutex);
impl Drop for Mutex { fn drop(&mut self) { println!("Mutex::drop"); } }
impl<'a> Drop for MutexGuard<'a> { fn drop(&mut self) { println!("MutexGuard::drop"); } }
impl Mutex {
fn lock(&self) -> Result<MutexGuard, ()> { Ok(MutexGuard(self)) }
}
fn main() {
let counter = Mutex;
if let Ok(_) = counter.lock() { }
//[edition2021]~^ ERROR: does not live long enough
// Up until Edition 2021:
// With this code as written, the dynamic semantics here implies
// that `Mutex::drop` for `counter` runs *before*
// `MutexGuard::drop`, which would be unsound since `MutexGuard`
// still has a reference to `counter`.
//
// The goal of #54556 is to explain that within a compiler
// diagnostic.
// From Edition 2024:
// Now `MutexGuard::drop` runs *before* `Mutex::drop` because
// the lifetime of the `MutexGuard` is shortened to cover only
// from `if let` until the end of the consequent block.
// Therefore, Niconii's issue is properly solved thanks to the new
// temporary lifetime rule for `if let`s.
}