Bil*_*lly 8 coercion dereference rust
在阅读了 Rust 书中关于智能指针和内部可变性的部分后,作为个人练习,我尝试编写一个函数来遍历智能指针的链表并返回列表中的“最后一个”元素:
#[derive(Debug, PartialEq)]
enum List {
Cons(Rc<RefCell<i32>>, Rc<List>),
Nil,
}
use crate::List::{Cons, Nil};
fn get_last(list: &List) -> &List {
match list {
Nil | Cons(_, Nil) => list,
Cons(_, next_list) => get_last(next_list),
}
}
Run Code Online (Sandbox Code Playgroud)
此代码导致以下错误:
| Nil | Cons(_, Nil) => list,
| ^^^ expected struct `std::rc::Rc`, found enum `List
Run Code Online (Sandbox Code Playgroud)
我能够通过使用“匹配保护”并明确取消对Cons(_, x)模式的引用来使其工作:
fn get_last(list: &List) -> &List {
match list {
Nil => list,
Cons(_, next_list) if **next_list == Nil => list,
Cons(_, next_list) => get_last(next_list),
}
}
Run Code Online (Sandbox Code Playgroud)
鉴于我对隐式取消引用和Dereftrait 实现的了解Rc,我本以为我的第一次尝试会成功。为什么我必须在这个例子中明确取消引用?
Apl*_*123 10
首先,我们需要了解什么是取消引用强制。如果T解引用U并且x是 type 的值T,则:
*x 是 *Deref::deref(&x)&T 可以被强制 &Ux.method()将U在方法解析期间检查类型。方法解析的工作原理是当您在类型上调用方法时,它首先通过向类型添加任何内容,然后添加&,然后添加&mut,然后取消引用来检查方法。因此,在确定要调用哪个方法时x.method(),它会首先检查采用T, then &T, then &mut T, then U, then &U, then 的方法&mut U(在此处阅读更多内容)。这并不适用于运营商。因此,==不会强制不同的类型,这就是您必须显式取消引用的原因。
但是如果我们确实使用了一个方法,比如.eq在PartialEqtrait 中呢?事情变得有趣。以下代码失败:
fn get_last(list: &List) -> &List {
match list {
Nil => list,
Cons(_, next_list) if next_list.eq(Nil) => list,
Cons(_, next_list) => get_last(next_list),
}
}
Run Code Online (Sandbox Code Playgroud)
但以下成功:
fn get_last(list: &List) -> &List {
match list {
Nil => list,
// notice how it's Nil.eq and not next_list.eq
Cons(_, next_list) if Nil.eq(next_list) => list,
Cons(_, next_list) => get_last(next_list),
}
}
Run Code Online (Sandbox Code Playgroud)
为什么是这样?我们来看第一个例子:
next_list是 type &Rc<List>,所以它开始搜索一个.eq方法。它立即找到一个在PartialEq实现中定义的Rcwith signature fn eq(&self, other: &Rc<List>)。但是,在这种情况下other是类型List,不能强制为&Rc<List>。
那为什么第二个工作呢?
Nil是 type List,所以它开始搜索一个.eq方法。它找不到任何 for List,所以它&List接下来尝试,在那里它找到PartialEq带有签名的派生实现fn eq(&self, other: &List)。在这种情况下, other 是 type &Rc<List>,&List由于它的Deref实现,可以强制转换为。这意味着所有类型检查都正确并且代码可以正常工作。
至于为什么你的第一次尝试没有成功,它似乎不是 Rust 中的一个功能,并且有一个可以追溯到 2017 的建议添加它。
| 归档时间: |
|
| 查看次数: |
415 次 |
| 最近记录: |