我有一个特点,我为dyn Trait实现了PartialEq(和Eq). 当我在Box<dyn Trait>Rc<dyn Trait>Arc<dyn Trait>上使用相等运算符时,会导致右操作数为moved而不是borrow . 为什么? 除其他事项外,这防止直接在这些值上使用assert_eq!.

docs for comparison operators人说:

与上面的算术和逻辑运算符不同,这些运算符隐式地接受操作数的共享borrow ,在表达式上下文中计算它们:

a == b;
// is equivalent to
::std::cmp::PartialEq::eq(&a, &b);

这意味着操作数不必移出.

我不明白为什么在这种情况下右操作数最终被移动. 在eq方法中,正确的操作数不应该以&Box<dyn Trait>(即借位)结束吗?

转载:(Playground)

use std::{
    fmt,
    rc::Rc,
    sync::Arc,
};

trait MyTrait : fmt::Debug {
    fn get_val(&self) -> u32;
}

#[derive(Clone, Debug)]
struct MyStruct {
    val: u32,
}

impl MyTrait for MyStruct {
    fn get_val(&self) -> u32 {
        self.val
    }
}

impl PartialEq for dyn MyTrait {
    fn eq(&self, other: &Self) -> bool {
        self.get_val() == other.get_val()
    }
}
impl Eq for dyn MyTrait {}

fn main() {
    // same error if you change `Box` to `Rc` or `Arc`
    let left:  Box<dyn MyTrait> = Box::new(MyStruct { val: 0 });
    let right: Box<dyn MyTrait> = Box::new(MyStruct { val: 42 });

//  assert_eq!(left, right); // error: cannot move out of `*right_val` [...]

    let _ = left == right; // moves `right`
    let _ = right.get_val(); // error: use of moved value
}

我找到了一些相对简单的解决办法:

  • 解释德苏加:left.eq(&right)(虽然对assert_eq!没有帮助)
  • 比较trait对象(即deref/unwrapped the own):*left == *right
  • 比较所有者参考:&left == &right
  • 比较trait对象引用:&*left == &*right
  • Option:Some(left) == Some(right)包装(有限的帮助,因为价值观仍然被移动—进入Options)

但是(a)需要他们有点不满意,(b)我仍然想知道为什么会发生这种情况.

推荐答案

这是一个编译器错误:问题#31740.

在错误被修复之前,你必须解决它.你的两个选项都有效,但我肯定会 Select 一个不移动它的参数.

Rust相关问答推荐

亚性状上位性状上的 rust 病伴生型界限

rust 迹-内存管理-POP所有权-链表

支持TLS的模拟HTTP服务器

当发送方分配给静态时,Tokio MPSC关闭通道

你能在Rust中弃用一个属性吗?

用于实现获取 struct 体 id 的特征规范

通过异常从同步代码中产生yield 是如何工作的?

Rust,如何从 Rc> 复制内部值并返回它?

如何在 Rust 中将函数项变成函数指针

Rust 1.70 中未找到 Trait 实现

在 Rust 中忽略 None 值的正确样式

OpenGL 如何同时渲染无纹理的四边形和有纹理的四边形

为什么带有生命周期指定的方法不能被调用两次?

max(ctz(x), ctz(y)) 有更快的算法吗?

如何将这些测试放在一个单独的文件中?

我的 Axum 处理程序无法编译:未实现 IntoResponse 特征

使用部分键从 Hashmap 中检索值

没有通用参数的通用返回

如何在没有 `make_contiguous()` 的情况下对 VecDeque 进行排序或反转?

如何在不设置精度的情况下打印浮点数时保持尾随零?