为何Rust中两个Fn约束的ProtocolItem trait实现会冲突?
为什么两个不同Fn签名的ProtocolItem泛型实现会冲突?
Rust类型系统通常对类型区分严格,哪怕外观相似的类型也会被视为不同,但在为函数实现trait时却出现了看似忽略参数差异的情况。比如下面这两个针对不同签名Fn的ProtocolItem泛型实现:
impl<T> ProtocolItem for T where T: Fn([u32; 8]) -> Result<Vec<u32>, MyError>, { fn handle(&self, _ctx: &Context, v: [u32; 8]) -> Result<Vec<u32>, MyError> { self(v) } }
impl<T> ProtocolItem for T where T: Fn(&Context, [u32; 8]) -> Result<Vec<u32>, MyError>, { fn handle(&self, ctx: &Context, v: [u32; 8]) -> Result<Vec<u32>, MyError> { self(ctx, v) } }
编译时会触发如下错误:
error[E0119]: conflicting implementations of trait
ProtocolItem
冲突原因
这本质是Rust泛型trait实现的重叠检查机制导致的:
- Rust要求所有trait实现必须是无歧义的,编译器会在泛型定义阶段检查是否存在某个类型可能同时满足多个实现的约束。
- 虽然我们知道普通函数/闭包不可能同时拥有两种不同的参数签名,但从类型系统的角度看,存在自定义类型手动同时实现这两个
Fntrait的可能性——比如一个结构体可以同时实现Fn([u32;8])->...和Fn(&Context, [u32;8])->...这两个trait。 - 由于编译器无法在泛型实现的定义阶段证明这两个约束是完全互斥的,因此会判定这两个实现存在潜在的重叠,从而抛出冲突错误。
简单来说,Rust的重叠检查不关心“实际有没有类型会同时满足约束”,只关心“理论上是否存在这样的类型”——只要理论上存在,就会被判定为冲突。
内容的提问来源于stack exchange,提问作者Simson
相关产品推荐
相关产品推荐

