Why does RefCell borrow() not allow a temp variable?

Question is in the comment below:

use std::cell::{RefCell};

fn handle(_:&str) {
    
}

fn main() {

    let foo = RefCell::new(Some("hello".to_owned()));
    //Why does this work
    handle(foo.borrow().as_ref().unwrap());
    
    //but this doesn't?
    let bar = foo.borrow().as_ref().unwrap();
    handle(bar);
}

playground

"temporary value is freed at the end of this statement"
This applies to any way you create temporary values. The opposite "temporary value created in argument exists until function call completes" is the basic rule that allows the first.

1 Like

There is exact error message here:
temporary value is freed at the end of this statement
You can do this:

let b = foo.borrow();
let bar = b.as_ref().unwrap();

and it works perfectly.

It is because calling foo.borrow() you got owned object of type Ref, and when you call as_ref on it, it just goes out of scope and is dropped - but there is borrow to it (returned by as_ref) which is illegal. What you need to do is to store Ref object somewhere, to prolong its lifetime till end of scope.

1 Like

Thanks for the breakdowns!

That seems like an incredibly useful rule... searching for it led me to dead-ends though. Is it documented somewhere?

I just know from experience, it has its down sides;

use std::cell::{RefCell};

fn handle(h:&str, c:&RefCell<Option<String>>) {
    if h == "hello" {
        *c.borrow_mut() = Some("world".to_owned());
    }
}

fn main() {
    let foo = RefCell::new(Some("hello".to_owned()));
    handle(&foo.borrow().as_ref().unwrap().to_owned(), &foo);
}
1 Like

https://doc.rust-lang.org/reference/expressions.html#temporary-lifetimes might be what you're looking for, I think?

It's not strictly function calls, but rather that everything in "one expression" is kept around until the end of that expression.

1 Like