为什么导入 Borrow 使得调用借用是 Borrow::borrow 而不是 RefCell::borrow

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

我错误地导入了

std::borrow::Borrow
并陷入了以下代码片段的错误消息:

use std::borrow::Borrow;
use std::rc::Rc;
use std::cell::RefCell;

fn next(current: Rc<RefCell<i32>>) {
    let m = (*current).borrow().abs(); //ok
    let l = current.borrow().abs(); //error
}

游乐场

问题是手动取消引用有效,但取消引用强制似乎不起作用:

error[E0282]: type annotations needed
 --> src/lib.rs:7:21
  |
7 |     let l = current.borrow().abs(); //error
  |                     ^^^^^^   --- type must be known at this point
  |
help: try using a fully qualified path to specify the expected types
  |
7 |     let l = <Rc<RefCell<i32>> as Borrow<Borrowed>>::borrow(&current).abs(); //error
  |             ++++++++++++++++++++++++++++++++++++++++++++++++    

如果删除

use std::borrow::Borrow;
,它会按预期工作:

let l = current.borrow().abs(); //ok

这种行为看起来很令人困惑。我认为

Rc: Borrow
已经很满意了,所以应该不会有任何差异。

重复的问题确实回答了为什么需要取消引用。它准确地说明了我在原始帖子中提到的内容。

rust smart-pointers borrow
1个回答
2
投票

罪魁祸首是this全面实施

Borrow

impl<T: ?Sized> Borrow<T> for T {
    fn borrow(&self) -> &T {
        self
    }
}

如果此 impl 在范围内(通过

use std::borrow::Borrow;
),则对
.borrow()
的调用是不明确的,因为
Rc<T>
实现了
Borrow<T>
本身

正如编译器所说,根据

l
的类型,应该调用不同的 impl:

fn next(current: Rc<i32>) {
    let m = (*current).borrow(); //ok
    // both of these are valid!
    let l_1: &Rc<i32> = current.borrow(); // uses `impl Borrow<T> for T` 
    let l_2: &i32 = current.borrow();     // uses `impl Borrow<T> for Rc<T>`
}

Playground(我在示例中将

Rc<RefCell<i32>>
替换为
Rc<i32>
, 因为它有点简单,但表现出相同的行为。 )

如果你先

Deref
*current
),它就不含糊的原因是 结果类型
i32
再次只有一个
impl
代表
Borrow

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