Rust中impl Foo for Foo的作用是什么?为何会导致Sized trait不满足对象安全要求
带Sized约束的trait不满足对象安全的原因
核心前提
- 所有对象安全的trait,编译器都会自动生成
impl Trait for dyn Trait的实现 Sized是Rust内置的标记trait,只有编译期能确定大小的类型才会自动实现该trait;dyn Trait属于动态大小类型(DST),编译期无法确定大小,天生不满足Sized约束
编译器自动生成impl Trait for dyn Trait的原因
这个设计是为了保证trait对象的通用性:当你写了一个要求参数实现某trait的泛型函数时,trait对象本身也可以直接作为参数传入。比如:
fn test<T: Foo>(arg: T) {}
如果没有impl Foo for dyn Foo,你就无法把dyn Foo类型的实例传给test函数,必须单独为&dyn Foo/Box<dyn Foo>等指针类型写额外的适配逻辑,使用体验很差。自动生成该实现后,trait对象本身就可以被当作实现了对应trait的普通类型处理,符合开发者的直觉。
带Sized约束的trait无法通过对象安全校验的原因
对象安全的核心要求之一,就是编译器能合法生成impl Trait for dyn Trait的实现。
当你给trait加上Sized父约束时:
trait Foo: Sized {}
意味着所有实现Foo的类型必须满足Sized约束,那编译器要生成impl Foo for dyn Foo时,首先要求dyn Foo: Sized,但dyn Foo是动态大小类型,天生不满足该约束,导致这个自动实现根本无法生成,所以Foo自然就不满足对象安全的要求,不能被用作trait对象。
内容的提问来源于stack exchange,提问作者Joey
相关产品推荐
相关产品推荐

