Rust中实现指定trait的类型无法传入泛型闭包的报错问题排查
错误原因
你遇到的编译错误本质是Rust泛型的约束规则导致的:
- 泛型参数
D的实际类型是**perform_sth的调用方**决定的,而非你在perform_sth实现内部决定。D: SomeTrait的约束仅表示「调用方传入的任意D类型都实现了SomeTrait」,不代表「你可以在实现里随便传入一个实现了SomeTrait的类型,就一定和调用方指定的D是同一个类型」。 - 举个例子:如果有另一个
struct AnotherType也实现了SomeTrait,调用方完全可以指定D=AnotherType来调用perform_sth,这时候你在实现里硬传SomeType的引用给要求&D的参数c,类型显然不匹配,编译器提前阻止了这种情况的发生。
解决方案
场景1:你的逻辑就是固定使用SomeType,不需要支持其他SomeTrait实现
直接移除泛型参数D,把闭包约束写死为接收&SomeType即可:
trait SomeOtherTrait { fn perform_sth<C>(&self, c: C) where C: Fn(&SomeType) -> &'static str; } impl SomeOtherTrait for SomeOtherType { fn perform_sth<C>(&self, c: C) where C: Fn(&SomeType) -> &'static str, { self.get_some_trait(|arg: SomeType| { c(&arg); }); } }
场景2:需要支持任意SomeTrait实现,由调用方指定具体类型
修改get_some_trait方法,把它也改成泛型支持任意实现SomeTrait的参数传入:
impl SomeOtherType { fn get_some_trait<C, T: SomeTrait>(&self, c: C, val: T) where C: Fn(T), { c(val); } } trait SomeOtherTrait { fn perform_sth<C, D>(&self, c: C, d: D) where D: SomeTrait, C: Fn(&D) -> &'static str; } impl SomeOtherTrait for SomeOtherType { fn perform_sth<C, D>(&self, c: C, d: D) where D: SomeTrait, C: Fn(&D) -> &'static str, { self.get_some_trait(|arg: D| { c(&arg); }, d); } }
场景3:需要运行时动态支持任意SomeTrait实现
可以用动态分发的trait对象,避免泛型参数的静态约束:
trait SomeOtherTrait { fn perform_sth<C>(&self, c: C) where C: Fn(&dyn SomeTrait) -> &'static str; } impl SomeOtherTrait for SomeOtherType { fn perform_sth<C>(&self, c: C) where C: Fn(&dyn SomeTrait) -> &'static str, { self.get_some_trait(|arg: SomeType| { c(&arg); }); } }
这种场景下闭包接收的是dyn SomeTrait trait对象的引用,所有实现了SomeTrait的类型都可以传入,不需要静态指定具体类型。
内容的提问来源于stack exchange,提问作者Jakub Padło
相关产品推荐
相关产品推荐

