如何在检查已经借用的字段时创建一个具有对自身的引用计数引用的值?

How to create a value with reference-counted references to itself while checking an already-borrowed field?

我正在尝试创建一个可变结构 B,它存储包含对 B 的引用的其他结构 A 的实例。我想要一个实现,这样对原始 B 所做的任何突变都会传播到 A 中保存的引用。

然而,在突变期间,我必须检查包裹在 A 实例中的 B 实例中的一个字段,从而打破了 "one mutable xor many immutable" 规则。我需要在可变借用的同时不可变地借用,但不可变借用在变异函数内部,不会超出其范围。

use std::cell::RefCell;
use std::rc::{Rc, Weak};

#[derive(Debug)]
struct A {
    t: Weak<RefCell<B>>,
}

#[derive(Debug)]
struct B {
    a: usize,
    item: Option<A>,
}

impl B {
    pub fn mutate(&mut self, item: A) {
        {
            let t = item.t.upgrade().unwrap();

            // This check has to be done.
            //
            assert![t.borrow().a == self.a, "not equal"];
            //      ~~~~~~~~~~ panics on this borrow
        }
        //
        // The immutable borrow should end here.

        self.item = Some(item);
        self.a += 1;
    }
}

fn main() {
    let b = B { item: None, a: 0 };

    let bc = Rc::new(RefCell::new(b));

    let f = A {
        t: Rc::downgrade(&bc),
    };

    bc.borrow_mut().mutate(f);

    println!["{:?}", bc.borrow().item.as_ref().unwrap().t.upgrade()];
}

playground

它恐慌:

thread 'main' panicked at 'already mutably borrowed: BorrowError'

仅使用 Rc<RefCell<B>> 能否满足这些要求?不然我是不是要沉入unsafe代码?

RefCell::borrow 的文档说:

Panics

Panics if the value is currently mutably borrowed. For a non-panicking variant, use try_borrow.

在知道任何现有借用必须是 self(因此相等)的情况下使用 try_borrow 允许您的代码编译:

let eq = t.try_borrow().map_or(true, |v| v.a == self.a);
assert![eq, "not equal"];

另请参阅: