You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何拥有型 trait 对象的相等运算符会移动右操作数?

为什么Box<dyn Trait>使用==会移动右操作数?

核心原因

当你为dyn MyTrait实现PartialEq后,Rust解析left == right(left/right为Box<dyn MyTrait>)时,会优先尝试将操作数解引用为dyn MyTrait,匹配你实现的PartialEq for dyn MyTrait。但由于dyn MyTrait是非 Sized(!Sized)类型,Rust无法直接对right进行「自动引用+解引用」(即生成&*right),反而会将整个Box<dyn MyTrait>移动,生成临时的trait对象后取引用传递给eq方法。这直接导致原right变量的所有权被转移,后续无法再使用。

而标准库为Box<T>实现的PartialEq<Box<U>>虽然理论上可用,但Rust的类型解析优先级会优先选择更「直接」的trait对象实现,而非经过Box包装层的实现。

为什么官方文档的自动引用规则不生效?

官方文档提到的「比较运算符会隐式获取操作数的共享借用」是针对Sized类型的常规场景。当涉及!Sized的trait对象时,Rust的自动引用机制会出现异常:!Sized类型无法直接作为值存储或传递,只能通过引用,但解析逻辑错误地选择了移动整个智能指针,而非借用后解引用为trait对象引用。

有效解决方案

你找到的几种方案都能解决问题,这里整理各方案的适用场景:

  • 比较trait对象引用:&*left == &*right
    明确指定借用trait对象,完全避免移动,适用于所有场景(包括assert_eq!)。
  • 比较所有者引用:&left == &right
    利用标准库Box<T>的PartialEq实现,内部自动解引用到trait对象比较,无移动,适合assert_eq!。
  • 解引用后比较:*left == *right
    直接比较trait对象,Rust会自动为两者添加引用,写法简洁且无移动。
  • 显式调用eq方法:left.eq(&right)
    明确调用Box<T>的eq方法,无移动,但无法直接用于assert_eq!。

内容的提问来源于stack exchange,提问作者Jayonas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 05:24:52