Mutable borrowing problem

I don't understand the compiler behavior in the following code :

struct Cache;

impl Cache {
    fn get_mut(&mut self, _key: i32) -> Option<&mut String> {
        todo!();
    }
    fn put(&mut self, _key: i32, _value: String) -> &mut String {
        todo!();
    }
}

// Doesn't compile: cache borrowed twice.
fn get(cache: &mut Cache) -> &mut String {
    if let Some(v) = cache.get_mut(4) {
        v
    } else {
        // Why is cache still borrowed here?
        cache.put(4, String::new())
    }
}

// Compiles.
fn main() {
    let mut cache = Cache;
    let value = if let Some(v) = cache.get_mut(4) {
        v
    } else {
        // ... and why is it not a problem here?
        cache.put(4, String::new())
    };
    value.clear(); // make sure value is used.
}

The current borrow-checker has some cases involving function boundaries where it rejects code that would otherwise be valid. In particlar, if you return a borrow, it incorrectly keeps that borrow alive in all future code paths, not just the code paths that return it.

This will work:

fn get(cache: &mut Cache) -> &mut String {
    if let Some(v) = cache.get_mut(4) {
        cache.get_mut(4).unwrap()
    } else {
        cache.put(4, String::new())
    }
}

Ah ok, thank you.