我错误地导入了
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(¤t).abs(); //error
| ++++++++++++++++++++++++++++++++++++++++++++++++
如果删除
use std::borrow::Borrow;
,它会按预期工作:
let l = current.borrow().abs(); //ok
这种行为看起来很令人困惑。我认为
Rc: Borrow
已经很满意了,所以应该不会有任何差异。
重复的问题确实回答了为什么需要取消引用。它准确地说明了我在原始帖子中提到的内容。
罪魁祸首是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
。