Repository: rust
Issue: Unclear lifetime advice from compiler when returning unit from if
Labels: A-diagnostics,T-compiler

### Code

```Rust
use std::cell::RefCell;

fn main() {
    let left: RefCell<i32> = RefCell::new(4);

    // Works:
    //
    // let left_borrowed = left.borrow();
    // if let _ = left_borrowed {}

    // Does not work:
    //
    if let _ = left.borrow() {}
}
```


### Current output

```Shell
warning: irrefutable `if let` pattern
  --> test.rs:13:8
   |
13 |     if let _ = left.borrow() {}
   |        ^^^^^^^^^^^^^^^^^^^^^
   |
   = note: this pattern will always match, so the `if let` is useless
   = help: consider replacing the `if let` with a `let`
   = note: `#[warn(irrefutable_let_patterns)]` on by default

error[E0597]: `left` does not live long enough
  --> test.rs:13:16
   |
4  |     let left: RefCell<i32> = RefCell::new(4);
   |         ---- binding `left` declared here
...
13 |     if let _ = left.borrow() {}
   |                ^^^^---------
   |                |
   |                borrowed value does not live long enough
   |                a temporary with access to the borrow is created here ...
14 | }
   | -
   | |
   | `left` dropped here while still borrowed
   | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Ref<'_, i32>`
   |
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
   |
13 |     if let _ = left.borrow() {};
   |                                +

error: aborting due to previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0597`.
```


### Desired output

_No response_

### Rationale and extra context

The compiler does a decent job at explaining what you should do, i.e. add a semicolon after the `if`. It does not do a good job at explaining why. The linked examples about temporaries not living enough don't really apply, as there is no obvious temporary involved.

What I believe is happening, is that the unit `()` returned from the `if` carries the lifetime of `left`. This is strange, because unit cannot borrow from anything.

Applying the compiler's suggestion does work, as it terminates the lifetime of the items borrowed for the `if`, and then returns a new unit value.

This is at least how I understand it, which may still be wrong and/or in need of polishing. The compiler should ideally just allow this pattern without modifications (since there is no temporary that outlives its lifetime), but barring that, it should at least provide some more specific pointers as to what temporary it thinks lives too long.

### Other cases

_No response_

### Rust Version

```Shell
rustc 1.75.0 (82e1608df 2023-12-21) (Arch Linux rust 1:1.75.0-2)
binary: rustc
commit-hash: 82e1608dfa6e0b5569232559e3d385fea5a93112
commit-date: 2023-12-21
host: x86_64-unknown-linux-gnu
release: 1.75.0
LLVM version: 16.0.6
```


### Anything else?

Tried to minimize the issue together with @arnavion. The RefCell or some other structure with complicated Drop semantics appears to be important, in other cases NLL appears to sidestep the issue.

**EDIT:** found a more minimal reproducer.