为何需同时为值与引用实现From trait?自动解引用为何不生效?
Rust中From/Into trait与自动解引用的适配问题
Rust的方法调用逻辑里,接收者会自动进行解引用或借用操作以匹配方法签名,比如示例中的两个方法:
into_char(self):接收Suit值,但可以被Suit值或其引用调用,引用会被自动解引用;to_char(&self):接收Suit的引用,但也可以被Suit值调用,值会被自动借用。
在当前代码中,我们同时为char实现了From<Suit>和From<&Suit> trait,因此:
- 当用
Suit值调用into()时,会触发Into<char>::into()(对应From<Suit>的实现); - 当用
&Suit调用into()时,会触发Into<char>::into()(对应From<&Suit>的实现)。
但问题在于:为什么必须同时实现这两个From?注释掉任意一个实现,编译器都会报错。
按照方法调用的候选类型生成逻辑,编译器会先为接收者生成一系列候选类型:反复解引用接收者,同时为每个候选类型T添加&T和&mut T,之后为每个候选类型查找对应的方法或trait实现。
假设只实现From<Suit>,那么根据From和Into的关联,Suit会自动实现Into<char>:
- 对于
value.into()(value是Suit值),候选类型包含Suit、&Suit、&mut Suit,可以直接匹配Into<char>::into(); - 对于
reference.into()(reference是&Suit),候选类型应该包含&Suit、&&Suit、&mut &Suit,以及解引用后的Suit,按逻辑应该能匹配到Into<char>::into(),但实际编译失败。
我的推导逻辑哪里有问题?为什么只实现一个From时无法完成自动适配?
#[derive(Clone, Copy)] pub enum Suit { Club, Diamond, Heart, Spade, } pub use Suit::*; impl Suit { #[inline(never)] pub fn into_char(self) -> char { match self { Club => 'C', Diamond => 'D', Heart => 'H', Spade => 'S', } } #[inline(never)] pub fn to_char(&self) -> char { match self { Club => 'C', Diamond => 'D', Heart => 'H', Spade => 'S', } } } impl std::convert::From<Suit> for char { fn from(suit: Suit) -> Self { suit.into_char() } } impl std::convert::From<&Suit> for char { fn from(suit: &Suit) -> Self { suit.to_char() } } fn main() { let value = Club; let reference = &value; let a: char = value.into_char(); let b: char = value.to_char(); let c: char = value.into(); println!("{}, {}, {}", a, b, c); let d: char = reference.into_char(); let e: char = reference.to_char(); let f: char = reference.into(); println!("{}, {}, {}", d, e, f); }
已创建简化的复现示例,并在Rust仓库提交了相关Issue。
内容的提问来源于stack exchange,提问作者scottwillmoore
相关产品推荐
相关产品推荐

