Why is this RefCell borrow not dropped inside its block?

I had something similar to the code below in a gtk+rust app and thought that might be related to gtk and its internal management of things, but I'm able to reproduce it without it.

The s variable is a RefCell, and this code panics because of "already borrowed".

// thread 'main' panicked at 'already borrowed: BorrowMutError'
if let Some(_) = s.borrow().get() {
    s.borrow_mut().set()
}

Now, to fix it I thought creating a narrower scope for the borrow would work, like this:

// thread 'main' panicked at 'already borrowed: BorrowMutError'
if let Some(_) = { s.borrow().get() } {
    s.borrow_mut().set()
}

but it doesn't, although I found othe two options that do work, I'm just curious about why my attempt at creating a scope didn't work.

// works
if let Some(_) = {
    let v = s.borrow().get();
    v
} {
    s.borrow_mut().set()
}

// also works
let v = s.borrow().get();
if let Some(_) = v {
    s.borrow_mut().set()
}

thanks y'all, here's a link to a playground with a working (or not) version of this Rust Playground

Ok, apparently the cause is that "temporaries live for the entire statement", as pointed out in this comment on github.

So in my first attempt the temporary scope wouldn't work because all of it values would last to the end of the if. While in the examples that work a statement ends, effectively dropping the temporary borrow.

You can read more about temporary scopes in the reference. if let is like a match, but the condition of a (plain) if is its own temporary scope. So you can also use:

    if s.borrow().get().is_some() {
        s.borrow_mut().set()
    }

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.