Lifetime and borrow rules in an if else branch

⚓ Rust    📅 2025-07-20    👤 surdeus    👁️ 3      

surdeus

I got trouble compile the following codes:

struct Bar {}
impl Bar {
    pub fn some_expensive_computation(&self) -> String {
        "42".to_string()
    }
}

struct Foo {
    m1: Option<i32>,
    m2: Bar,
}
impl Foo {
    pub fn f2 (&mut self) -> Option<&i32> {
        match &self.m1 {
            Some(f1) => Some(f1),
            None => None,
        }
    }
    pub fn f1(&mut self) -> Result<&i32, String> {
        if let Some(f1) = self.f2() {
            Ok(f1)
        } else {
            Err(self.m2.some_expensive_computation())
        }
    }
}

And the compiler report errors:

error[E0502]: cannot borrow `self.m2` as immutable because it is also borrowed as mutable
  --> src\main.rs:23:17
   |
19 |     pub fn f1(&mut self) -> Result<&i32, String> {
   |               - let's call the lifetime of this reference `'1`
20 |         if let Some(f1) = self.f2() {
   |                           ---- mutable borrow occurs here
21 |             Ok(f1)
   |             ------ returning this value requires that `*self` is borrowed for `'1`
22 |         } else {
23 |             Err(self.m2.some_expensive_computation())
   |                 ^^^^^^^ immutable borrow occurs here

I'm confused about this error. I think in this case only one branch will actually got run, I don't understand why the self in if branch will affect the self in else.

And if I wrote like this:

    pub fn f1(&mut self) -> Result<&i32, String> {
        let err = Err(self.m2.some_expensive_computation());
        if let Some(f1) = self.f2() {
            Ok(f1)
        } else {
            err
        }
    }
        

It will compile. But as the function name suggests, it's expensive and should not do that out of "else" branch.

I appreciate it if someone could help to tell if this is a limitation of borrow checker or there's indeed a potential safety problem.

If it's a limitation, I'm curious what's the lifetime/borrow rules for a if let Some(v) = f() {...} else {...}

5 posts - 3 participants

Read full topic

🏷️ rust_feed