Course contentsShow
← Rust
Lesson 261 of 1,9103. Borrowing and ReferencesFree lesson

Borrowing from RefCell

Handle runtime borrow checking failures in RefCell gracefully.

In this lesson, you will learn how to handle runtime borrow checking failures in RefCell gracefully so your program doesn't panic.

The RefCell Trap

As we know, RefCell<T> allows us to bypass the compiler's strict borrow checker by moving the "is this safe?" check from compile-time to runtime. However, just because we moved the check doesn't mean the rules changed. If you try to call .borrow_mut() while an existing .borrow() is active, your program will panic and crash.

In production code, crashing is rarely the desired outcome. Instead of blindly using .borrow() or .borrow_mut(), we can use methods that return an Option or a Result, allowing us to handle the conflict safely.

Using try_borrow and try_borrow_mut

Instead of the standard methods that trigger a panic, we use try_borrow() and try_borrow_mut(). These return a Result<T, BorrowError>, which lets us decide what to do if the borrow fails.

use std::cell::RefCell;

fn main() {
    let data = RefCell::new(5);

    let _reader = data.borrow(); // We hold an immutable reference

    // Attempt to borrow mutably without panicking
    match data.try_borrow_mut() {
        Ok(mut val) => *val += 1,
        Err(_) => println!("Conflict detected: Cannot borrow mutably while reading!"),
    }
}

Why this matters

By using the try_ versions of these methods, you treat borrow-checking failures like any other runtime error, such as a file not being found. You can log the error, skip the operation, or retry it later. This makes your code robust, especially when managing complex data structures where multiple components might unknowingly try to access the same RefCell at once.

Always remember: RefCell doesn't make the borrowing rules go away; it just provides a mechanism to handle them dynamically. When you cannot guarantee that your code paths won't overlap, try_borrow and try_borrow_mut are your best tools for avoiding runtime crashes.

Key Takeaway: Use try_borrow and try_borrow_mut to handle borrow conflicts as recoverable errors instead of letting your program panic.