Rust中如何从trait对象的函数返回动态类型值?
Rust 动态 trait 对象编译错误解决
问题代码
trait A {} trait B { type C: A; fn foo(self) -> Self::C; } fn process(b: Box<dyn B<C = dyn A>>) -> Box<dyn A> { Box::new(b.foo()) }
错误信息
error[E0277]: 无法在编译时确定类型 `(dyn A + 'static)` 的大小 --> tests/test.rs:9:16 | 9 | Box::new(b.foo()) | ^^^ 编译时无法确定大小 | = help: 特征 `Sized` 未为 `(dyn A + 'static)` 实现
问题原因
dyn A 是动态大小类型(DST),而 foo 方法返回的 Self::C 在这里被指定为 dyn A。但 Rust 里函数返回值默认要求是大小确定的类型(实现 Sized trait),Box::new 也需要接收一个编译时大小已知的值,直接返回 dyn A 不符合要求,因为编译器没法知道它的具体大小。
解决方法
有两种常见的修复思路:
方案一:让 foo 直接返回装箱后的 trait 对象
把 foo 的返回类型改成 Box<dyn A>,这样就不需要关联类型直接对应 dyn A:
trait A {} trait B { fn foo(self) -> Box<dyn A>; } fn process(b: Box<dyn B>) -> Box<dyn A> { b.foo() }
方案二:允许关联类型是动态大小类型
给关联类型加上 ?Sized 约束,同时让 foo 返回 Box<Self::C>,用装箱来包裹动态大小的类型:
trait A {} trait B { type C: A + ?Sized; // 允许关联类型是动态大小类型 fn foo(self) -> Box<Self::C>; } fn process(b: Box<dyn B<C = dyn A>>) -> Box<dyn A> { b.foo() }
核心要点
- 动态 trait 对象(
dyn Trait)属于动态大小类型,不能直接作为函数返回值,必须用指针、装箱这类方式包裹 Sized是 Rust 默认的 trait 约束,函数返回值默认要求实现该 trait,如果要支持动态大小类型,需要显式标注?Sized
内容的提问来源于stack exchange,提问作者creaple
相关产品推荐
相关产品推荐

