为什么 Rust 需要双重借用 (`&&'a mut T`)

Mar*_*ark 0 types rust borrow-checker borrowing

我的代码如下所示

pub enum Cache<'a, T> {
    Pending(&'a dyn FnOnce() -> T),
    Cached(T),
}

impl<'a, T> Cache<'a, T> {
    pub fn get(&self) -> &mut T {
        // This caches and borrows the T
    }
}

impl<'a, T> PartialEq for Cache<'a, T>
    where &'a mut T: PartialEq {

    fn eq(&self, other: &Self) -> bool {
        self.get().eq(other.get())
    }
}
Run Code Online (Sandbox Code Playgroud)

但实施Eq失败:

pub enum Cache<'a, T> {
    Pending(&'a dyn FnOnce() -> T),
    Cached(T),
}

impl<'a, T> Cache<'a, T> {
    pub fn get(&self) -> &mut T {
        // This caches and borrows the T
    }
}

impl<'a, T> PartialEq for Cache<'a, T>
    where &'a mut T: PartialEq {

    fn eq(&self, other: &Self) -> bool {
        self.get().eq(other.get())
    }
}
Run Code Online (Sandbox Code Playgroud)

我想我在概念上误解了一些东西。

Sve*_*ach 5

您可以通过查看特征中方法&&mut T的定义来理解为什么 Rust 需要 an :eq()PartialEq

\n\n
fn eq(&self, other: &Rhs) -> bool;\n
Run Code Online (Sandbox Code Playgroud)\n\n

该方法的参数类型为&Self&Rhs;由于Rhs默认为Self且您没有在特征绑定中指定任何其他内容,因此两个参数都应为 类型&Self

\n\n

现在Self这个例子是什么?你的特质界限是这样的:

\n\n
&'a mut T: PartialEq\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此编译器可以使用的唯一PartialEq实现是 type 的实现&'a mut T,所以这就是Self&Self反过来,必须是&&'a mut T,这正是编译器所期望的。

\n\n

您可能想要的特征T是:

\n\n
impl<'a, T> PartialEq for Cache<'a, T>\nwhere\n    T: PartialEq,\n{\n    fn eq(&self, other: &Self) -> bool {\n        self.get() == other.get()\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

另请注意,您可以简单地使用==而不是显式调用eq(). 它使得获得正确的类型变得更容易,因为编译器将隐式地获取参数的引用 \xe2\x80\x93a == b扩展为PartialEq::eq(&a, &b).

\n