为何Deref coercion在无类型不匹配场景下仍被触发?
Rust中Trait方法调用的匹配优先级问题
你的困惑核心不是Deref强制转换,而是Rust的方法解析规则——编译器在匹配Trait方法时,会优先选择接收者类型与方法的&self参数最直接匹配的实现,而非你预期的基于变量本身类型的实现。
代码分析
第一段代码中,只有impl Tr for &X,调用r.show()时,r是&X类型,编译器只能找到Tr对&X的实现:此时show方法的&self是&&X,编译器会自动对r取引用(&r)来匹配参数,因此输出referenced。
第二段代码新增了impl Tr for X,此时调用r.show()时,编译器有两个匹配路径:
- 匹配
impl Tr for &X:需要将r(&X)再取一次引用得到&&X,对应show的&self参数; - 匹配
impl Tr for X:show的&self是&X,而r本身就是&X(&*r等价于r),完全匹配参数类型,无需额外转换。
编译器会优先选择无需额外引用/解引用转换的路径,因此最终调用的是impl Tr for X的show方法,输出owned。
让输出回到referenced的方法
除了泛型Trait Bound,还有几种直接的方式:
- 显式取引用:
fn main() { let x = X; let r = &x; (&r).show(); // prints referenced } trait Tr { fn show(&self); } struct X; impl Tr for &X { fn show(&self) { println!("referenced"); } } impl Tr for X { fn show(&self) { println!("owned"); } }
(&r)是&&X类型,此时编译器会匹配impl Tr for &X的实现,因为show的&self参数正好是&&X。
- 使用完全限定语法明确指定Trait实现:
fn main() { let x = X; let r = &x; <&X as Tr>::show(&r); // prints referenced } trait Tr { fn show(&self); } struct X; impl Tr for &X { fn show(&self) { println!("referenced"); } } impl Tr for X { fn show(&self) { println!("owned"); } }
直接指定使用&X的Tr实现,避免编译器自动选择。
- 显式转换类型:
fn main() { let x = X; let r = &x; let rr: &&X = &r; rr.show(); // prints referenced } trait Tr { fn show(&self); } struct X; impl Tr for &X { fn show(&self) { println!("referenced"); } } impl Tr for X { fn show(&self) { println!("owned"); } }
将r转换为&&X类型,调用时自然匹配&X的Trait实现。
内容的提问来源于stack exchange,提问作者Santhosh Kumar Tekuri
相关产品推荐
相关产品推荐

