意外的自动取消引用行为

问题描述 投票:3回答:1

当尝试将双重链接列表包含在rust中时,我发现以下意外错误

if let Some(link) = self.tail.take() {
    let x = link.borrow_mut();
    link.borrow_mut().next = Some(node.clone());
} else { ... }

这里的链接被推断为Rc<RefCell<Node<..>>>,编译器说:

不能借用不可变的局部变量link作为可变变量。

[尝试后,我想当use std::borrow::BorrowMut时发生错误。

// compiles
fn test1() {
    let a = Rc::new(RefCell::new(1));
    let b = RefCell::new(1);
    b.borrow_mut();
    a.borrow_mut();
}

// doesn't compile
fn test2() {
    use std::borrow::BorrowMut; // inserted this import!

    let a = Rc::new(RefCell::new(1));
    let b = RefCell::new(1);
    b.borrow_mut();
    a.borrow_mut();
}

此处test2()无法编译。我想知道为什么这样工作。

rust dereference
1个回答
1
投票

想要调用的是方法RefCell::borrow_mut()

但是,RefCell::borrow_mut()a而不是Rc,因此它没有RefCell方法。这是自动解引用输入图片的地方。因为borrow_mut实现了Rc<RefCell<T>>特征,所以可以在方法调用时将其自动取消引用到Deref,而这正是第一次测试中发生的情况。

现在,如果我们导入Deref特征,则测试将停止工作。这是因为&RefCell<T>特性还具有一种称为BorrowMut的方法,即BorrowMut

borrow_mut

这意味着implemented for all types现在有impl<T: ?Sized> BorrowMut<T> for T { ... } 方法可用,因此没有Deref强制发生,并且我们的代码调用了错误的方法。

© www.soinside.com 2019 - 2024. All rights reserved.