Repository: rust
Issue: edition 2024 migration of `Command::before_exec` is suboptimal and doesn't compile
Labels: A-lints,T-compiler,C-bug,A-edition-2024,I-edition-triaged

I ran `cargo +nightly fix --edition` on this code:

```rust
pub fn spawn_child() {
    let _status = Command::new("some_program")
        .before_exec(|| {
            unsafe {
                // Make the child process its own process group leader
                if libc::setpgid(0, 0) != 0 {
                    return Err(std::io::Error::last_os_error());
                }
                Ok(())
            }
        })
        .status();
}
```

And it made the following changes:
```rust
pub fn spawn_child() {
    // TODO: Audit that the closure is async-signal-safe.
    let _status = unsafe { Command::new("some_program")
        .before_exec(|| {
            unsafe {
                // Make the child process its own process group leader
                if libc::setpgid(0, 0) != 0 {
                    return Err(std::io::Error::last_os_error());
                }
                Ok(())
            }
        }) }
        .status();
}
```

The output is unsatisfying in a few ways:
1. There are now two `unsafe` blocks, triggering the `unused_unsafe` lint.
2. `before_exec` is still deprecated, so perhaps it should just be replaced with `pre_exec`?
3. The formatting is a bit weird; The newly added braces should get additional line breaks.
4. The code doesn't compile once I add `edition = "2024"` to `Cargo.toml`:

```plaintext
error[E0716]: temporary value dropped while borrowed
  --> src/lib.rs:7:9
   |
7  |           Command::new("some_program").before_exec(|| {
   |           -^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |           |
   |  _________creates a temporary value which is freed while still in use
   | |
8  | |             unsafe {
9  | |                 // Make the child process its own process group leader
10 | |                 if libc::setpgid(0, 0) != 0 {
...  |
14 | |             }
15 | |         })
   | |          -
   | |          |
   | |__________temporary value is freed at the end of this statement
   |            borrow later used here
   |
   = note: consider using a `let` binding to create a longer lived value
```

I wouldn't have submitted an issue based on the first three, but since `cargo fix` is responsible for the new structure of the code, it seems like the failure to compile should have been avoidable.

I am confused about why this doesn't build. Why does `pre_exec` / `before_exec` cause there to be a dropped-while-borrowed temporary under the 2024 edition where none existed previously?

To repair the broken build, I guess something like this is required? (The `let mut cmd` part.)
```rust
pub fn spawn_child() {
    let mut cmd = Command::new("some_program");
    let _status = unsafe {
        cmd.pre_exec(|| {
            // Make the child process its own process group leader
            if libc::setpgid(0, 0) != 0 {
                return Err(std::io::Error::last_os_error());
            }
            Ok(())
        })
    }
    .status();
}
```

### Meta
<!--
If you're using the stable version of the compiler, you should also check if the
bug also exists in the beta or nightly versions.
-->

`rustc --version --verbose`:
```
rustc 1.85.0-nightly (c94848c04 2024-12-05)
binary: rustc
commit-hash: c94848c046d29f9a80c09aae758e27e418a289f2
commit-date: 2024-12-05
host: x86_64-unknown-linux-gnu
release: 1.85.0-nightly
LLVM version: 19.1.5
```