[solved]Question about the example in std::cell


#1

There is an example in https://doc.rust-lang.org/std/cell/

++++++++++++++++++++++++++++++++++++++++++++++
use std::cell::RefCell;
struct Graph {
    edges: Vec<(i32, i32)>,
    span_tree_cache: RefCell<Option<Vec<(i32, i32)>>>
}

impl Graph {
    fn minimum_spanning_tree(&self) -> Vec<(i32, i32)> {
        // Create a new scope to contain the lifetime of the
        // dynamic borrow
        {
            // Take a reference to the inside of cache cell
            let mut cache = self.span_tree_cache.borrow_mut();
            if cache.is_some() {
                return cache.as_ref().unwrap().clone();
            }

            let span_tree = self.calc_span_tree();
            *cache = Some(span_tree);
        }

        // Recursive call to return the just-cached value.
        // Note that if we had not let the previous borrow
        // of the cache fall out of scope then the subsequent
        // recursive borrow would cause a dynamic thread panic.
        // This is the major hazard of using `RefCell`.
        self.minimum_spanning_tree()
    }
}
+++++++++++++++++++++++++++++++++++++

The code comments says:"
//Note that if we had not let the previous borrow
//of the cache fall out of scope then the subsequent
// recursive borrow would cause a dynamic thread panic.
"
So,i remove the braces:

++++++++++++++++++++++++++++++++++++
fn main() {
    #![allow(dead_code)]
use std::cell::RefCell;

struct Graph {
    edges: Vec<(i32, i32)>,
    span_tree_cache: RefCell<Option<Vec<(i32, i32)>>>
}

impl Graph {
    fn minimum_spanning_tree(&self) -> Vec<(i32, i32)> {
        // Create a new scope to contain the lifetime of the
        // dynamic borrow

            // Take a reference to the inside of cache cell
            let mut cache = self.span_tree_cache.borrow_mut();
            if cache.is_some() {
                return cache.as_ref().unwrap().clone();
            }

            let span_tree = self.calc_span_tree();
            *cache = Some(span_tree);


        // Recursive call to return the just-cached value.
        // Note that if we had not let the previous borrow
        // of the cache fall out of scope then the subsequent
        // recursive borrow would cause a dynamic thread panic.
        // This is the major hazard of using `RefCell`.
        self.minimum_spanning_tree()
    }
  fn calc_span_tree(&self) -> Vec<(i32, i32)> { vec![] }
}

let s=Graph{edges:vec![(1, 5)],span_tree_cache:RefCell::new(Some(vec![(1, 5)]))};
println!("{:?}",s.minimum_spanning_tree());
}
+++++++++++++++++++++++++++++++++++++++++

But when I test the codes at playground,and there is no panic.Did i misunderstand any thing?


#2

It never makes it to the problematic line, because you set the cache when you created the Graph. Change it to None, and…

thread 'main' panicked at 'RefCell<T> already borrowed', ../src/libcore/cell.rs:492

#3

:sweat:I’am sorry. Thank you for your patience.