为何Sized trait无法被转化为trait object?
为什么
Sized超trait会阻止trait被用作trait object? 问题背景
当我们定义一个无约束的trait时,代码可以正常编译:
trait Trait {} struct Foo {} impl Trait for Foo {} fn do_work(_: &dyn Trait) {}
但如果为Trait添加Sized作为超trait:
trait Trait: Sized {}
编译会失败并抛出如下错误:
error[E0038]: the trait `Trait` cannot be made into an object --> src\main.rs:6:16 | 6 | fn do_work(_: &dyn Trait) {} | ^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> src\main.rs:1:14 | 1 | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized`
已知Sized超trait会破坏对象安全性,但不理解背后逻辑,特此请教:为何Sized超trait会阻止trait被用作trait object?
解答
Sizedtrait的核心作用是标记编译时大小已知的类型。当你把Sized设为超trait时,不仅要求所有实现该trait的类型必须是Sized,更关键的是这个约束会直接作用于trait object本身。trait object(比如dyn Trait)是动态类型的载体,它可以指向任意实现了Trait的类型实例——不同实例的大小可能完全不同,因此trait object本身的大小在编译时是无法确定的,属于非Sized类型。- 当你要求
trait必须继承Sized时,就等同于强制要求trait object满足Sized约束,但这和trait object的动态特性完全矛盾。编译器为了避免这种逻辑冲突,会直接报错禁止将该trait构造成对象。
总结来说:Sized要求类型大小编译时可知,而trait object是动态大小类型,两者本质不兼容,因此添加Sized超trait会直接破坏trait的对象安全性。
内容的提问来源于Stack Exchange,提问作者aedm
相关产品推荐
相关产品推荐

