rust-lang / rust-lang/rust-clippy

Clippy suggestion on `unnecessary_unwrap` not applicable in function taking `&mut` struct and returning reference to contained element

Open
#16,182 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C-bug I-suggestion-causes-error
Dominant language
Rust
Stars
13.5k
Forks
2.2k
Avg merge
2d 10h
Merged PRs (30d)
32

Description

Summary

The following code triggers the unnecessary_unwrap lint, which is understandable, since there is in fact a is_some check followed by an unwrap. However, rewriting the code as suggested by results in the function not compiling (see the commented-out version in the repro):

error[E0502]: cannot borrow `self.opt` as mutable because it is also borrowed as immutable
  --> src/main.rs:19:9
   |
15 |     fn repro(&mut self) -> &String {
   |              - let's call the lifetime of this reference `'1`
16 |         if let Some(val) = &self.opt {
   |                            --------- immutable borrow occurs here
17 |             return val;
   |                    --- returning this value requires that `self.opt` is borrowed for `'1`
18 |         }
19 |         self.opt.insert(String::new())
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here

For more information about this error, try `rustc --explain E0502`.

If there is a more idiomatic way of writing this, it would be nice to get a corresponding suggestion. Otherwise, it might be better to disable the lint for such cases. If it is not feasible to correctly identify cases where the current suggestion does not work, it might be acceptable to keep the current behavior and require manual deactivation of the lint for the affected code via annotations.

Reproducer

Code:

struct Wrapper {
    opt: Option<String>,
}

impl Wrapper {
    fn repro(&mut self) -> &String {
        if self.opt.is_some() {
            return self.opt.as_ref().unwrap();
        }
        self.opt.insert(String::new())
    }

    /*
     * fn repro(&mut self) -> &String {
     *     if let Some(val) = &self.opt {
     *         return val;
     *     }
     *     self.opt.insert(String::new())
     * }
     */
}

fn main() {
    let mut wrapper = Wrapper { opt: None };
    let _ = wrapper.repro();
}

Current output:

warning: called `unwrap` on `self.opt` after checking its variant with `is_some`
 --> src/main.rs:8:20
  |
7 |         if self.opt.is_some() {
  |         --------------------- help: try: `if let Some(<item>) = &self.opt`
8 |             return self.opt.as_ref().unwrap();
  |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap
  = note: `#[warn(clippy::unnecessary_unwrap)]` on by default

Desired output:

a suggestion for more idiomatic code which compiles, or, if that's not possible, no lint for this code

Version
rustc 1.93.0-nightly (1d60f9e07 2025-12-01)
binary: rustc
commit-hash: 1d60f9e070c1039b263e0f035c0f03dfcc610d0f
commit-date: 2025-12-01
host: x86_64-unknown-linux-gnu
release: 1.93.0-nightly
LLVM version: 21.1.5
Additional Labels

@rustbot label +I-suggestion-causes-error

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Rust reproducer in the issue and inspect the unnecessary_unwrap lint and its suggestion. Run Clippy against the example, then verify that the suggested rewrite compiles or that the lint is omitted for this case.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.