Repository: rust-lang/rust-clippy (Rust)

Issue:
`manual_let_else` should surround `unsafe {}` with brackets `()`.
### Summary

Clippy suggests code that does not compile.



### Lint Name

manual_let_else

### Reproducer

I tried this code:

```rust
unsafe fn something_unsafe() -> Option<u32> {
    None
}

fn main() {
    let value = if let Some(value) = unsafe { something_unsafe() } {
        value
    } else {
        return;
    };

    println!("{}", value);
}
```

I saw this happen:

```rust
warning: this could be rewritten as \`let...else\`
  --> src/main.rs:6:5
   |
 6 | /     let value = if let Some(value) = unsafe { something_unsafe() } {
 7 | |         value
 8 | |     } else {
 9 | |         return;
10 | |     };
   | |______^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else
   = note: `-W clippy::manual-let-else` implied by `-W clippy::pedantic`
   = help: to override `-W clippy::pedantic` add `#[allow(clippy::manual_let_else)]`
help: consider writing
   |
 6 ~     let Some(value) = unsafe { something_unsafe() } else {
 7 +         return;
 8 +     };
   |
```

I expected to see this happen:

Nothing, I wouldn't expect the lint to trigger.

Accepting the lint's suggestion:

```
let Some(value) = unsafe { something_unsafe() } else {
    return;
};
```

Fails to compile:


```
error: right curly brace `}` before `else` in a `let...else` statement not allowed
 --> src/main.rs:6:51
  |
6 |     let Some(value) = unsafe { something_unsafe() } else {
  |                                                   ^
  |
help: wrap the expression in parentheses
  |
6 |     let Some(value) = (unsafe { something_unsafe() }) else {
  |                       +                             +
```

Subsequently wrapping it does work.


### Version

```text
❯ cargo clippy --version
clippy 0.1.90 (1159e78c47 2025-09-14)
```

### Additional Labels

_No response_

<!-- TRIAGEBOT_START -->

<!-- TRIAGEBOT_ASSIGN_START -->

<!-- TRIAGEBOT_ASSIGN_END -->
<!-- TRIAGEBOT_END -->


Discussion:
@rustbot claim




Patch:
diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs
index 298bf1075489..0f3d8b336675 100644
--- a/clippy_lints/src/manual_let_else.rs
+++ b/clippy_lints/src/manual_let_else.rs
@@ -183,7 +183,13 @@ fn emit_manual_let_else(
                 format!("{{ {sn_else} }}")
             };
             let sn_bl = replace_in_pattern(cx, span, ident_map, pat, &mut app, true);
-            let sugg = format!("let {sn_bl} = {sn_expr} else {else_bl};");
+            let sugg = if sn_expr.ends_with('}') {
+                // let-else statement expressions are not allowed to end with `}`
+                // https://rust-lang.github.io/rfcs/3137-let-else.html#let-pattern--if--else--else-
+                format!("let {sn_bl} = ({sn_expr}) else {else_bl};")
+            } else {
+                format!("let {sn_bl} = {sn_expr} else {else_bl};")
+            };
             diag.span_suggestion(span, "consider writing", sugg, app);
         },
     );


Test patch:
diff --git a/tests/ui/manual_let_else.rs b/tests/ui/manual_let_else.rs
index 3781ba1676f5..160e321d9a1e 100644
--- a/tests/ui/manual_let_else.rs
+++ b/tests/ui/manual_let_else.rs
@@ -546,3 +546,28 @@ mod issue14598 {
         todo!()
     }
 }
+
+mod issue15914 {
+    // https://github.com/rust-lang/rust-clippy/issues/15914
+    unsafe fn something_unsafe() -> Option<u32> {
+        None
+    }
+
+    fn foo() {
+        let value = if let Some(value) = unsafe { something_unsafe() } {
+            //~^ manual_let_else
+            value
+        } else {
+            return;
+        };
+
+        let some_flag = true;
+
+        let value = if let Some(value) = if some_flag { None } else { Some(3) } {
+            //~^ manual_let_else
+            value
+        } else {
+            return;
+        };
+    }
+}
diff --git a/tests/ui/manual_let_else.stderr b/tests/ui/manual_let_else.stderr
index a1eea0419291..f4b1644c44ba 100644
--- a/tests/ui/manual_let_else.stderr
+++ b/tests/ui/manual_let_else.stderr
@@ -549,5 +549,41 @@ LL | |             Some(x) => x,
 LL | |         };
    | |__________^ help: consider writing: `let Some(v) = w else { return Err("abc") };`
 
-error: aborting due to 35 previous errors
+error: this could be rewritten as `let...else`
+  --> tests/ui/manual_let_else.rs:557:9
+   |
+LL | /         let value = if let Some(value) = unsafe { something_unsafe() } {
+LL | |
+LL | |             value
+LL | |         } else {
+LL | |             return;
+LL | |         };
+   | |__________^
+   |
+help: consider writing
+   |
+LL ~         let Some(value) = (unsafe { something_unsafe() }) else {
+LL +             return;
+LL +         };
+   |
+
+error: this could be rewritten as `let...else`
+  --> tests/ui/manual_let_else.rs:566:9
+   |
+LL | /         let value = if let Some(value) = if some_flag { None } else { Some(3) } {
+LL | |
+LL | |             value
+LL | |         } else {
+LL | |             return;
+LL | |         };
+   | |__________^
+   |
+help: consider writing
+   |
+LL ~         let Some(value) = (if some_flag { None } else { Some(3) }) else {
+LL +             return;
+LL +         };
+   |
+
+error: aborting due to 37 previous errors