Rust中Trait方法接收&Self参数的默认实现编译错误如何解决?
Rust Trait默认方法接收同类型引用的编译错误解决方案
错误根因分析
- 第一个编译错误的原因:Trait默认方法中的
self本身已经是&Self类型,你调用全局add时写的&self会生成&&Self类型,和第一个参数要求的&T不匹配,编译器优先报参数类型不匹配的问题,导致你误以为是other的类型判断出错。 - 第二个编译错误的原因:当你给
other也加引用变成&other时,两个参数都变成了&&Self类型,而你的全局add要求类型T实现S,默认你没有给引用类型&Self实现STrait,因此报错。 - 第三个编译错误的原因:Rust中Trait的
Self默认不携带Sized约束(即允许动态大小类型实现该Trait),而泛型函数的参数T默认要求Sized(编译期可知大小),当你直接传self和other时,Self没有Sized约束,不满足泛型函数的要求,因此报大小未知错误。
可行解决方案
这种需求完全可以通过Trait默认实现完成,有三种常用改造方案:
方案1:给Trait增加Sized约束
如果你的Trait只会给编译期可知大小的具体类型实现,直接给Trait加上Sized约束即可,默认方法内直接传self和other调用全局函数:
struct A { val: f32, } // 加Sized约束,要求所有实现S的类型编译期大小可知 trait S: Sized { fn val(&self) -> f32; fn add(&self, other: &Self) -> f32 { add(self, other) } } impl S for A { fn val(&self) -> f32 { self.val } } fn add<T: S>(first: &T, second: &T) -> f32 { first.val() + second.val() }
方案2:仅给默认方法加Sized约束,不限制整个Trait
如果你需要保留Trait给动态大小类型实现的能力,只给需要默认实现的方法加约束即可:
trait S { fn val(&self) -> f32; // 仅该默认方法要求Self是Sized,不影响其他方法 fn add(&self, other: &Self) -> f32 where Self: Sized { add(self, other) } }
方案3:给全局泛型函数取消Sized约束
如果你不想给Trait加任何Sized相关的约束,可以修改全局add函数的泛型约束,允许动态大小类型:
// 加?Sized取消默认的Sized要求 fn add<T: S + ?Sized>(first: &T, second: &T) -> f32 { first.val() + second.val() } trait S { fn val(&self) -> f32; fn add(&self, other: &Self) -> f32 { add(self, other) } }
内容的提问来源于stack exchange,提问作者Maxim Gritsenko
相关产品推荐
相关产品推荐

