You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust编译错误:boxed trait对象大小编译期未知,求代码修改方案

Rust Trait对象编译错误:dyn MyTrait大小无法确定的解决办法

问题代码

trait MyTrait {
    fn foo(&self);
}

struct A {}

impl MyTrait for A {
    fn foo(&self) {
        println!("A");
    }
}

struct B {}

impl MyTrait for B{
    fn foo(&self) {
        println!("B");
    }
}

enum MyEnum {
    A,
    B,
}

fn create_object(my_enum: MyEnum) -> Box<dyn MyTrait> {
    let boxed_value: Box<dyn MyTrait> = match my_enum {
        MyEnum::A => Box::new(A{}),
        MyEnum::B => Box::new(B{}),
    };
    boxed_value
}

struct C<Allocator>
where Allocator: MyTrait + ?Sized {
    a: Box<Allocator>,
}

impl<Allocator> C<Allocator>
where Allocator: MyTrait {
    pub fn new(a: Box<Allocator>) -> Self {
        Self {a: a}
    }
}


fn main() {
    let boxed_value = create_object(MyEnum::A);
    C::new(boxed_value);
}

编译错误信息

编译 playground v0.0.1 (/playground)
error[E0277]: 类型`dyn MyTrait`的值大小在编译期无法确定
  --> src/main.rs:49:12
   |
49 |     C::new(boxed_value);
   |     ------ ^^^^^^^^^^^ 编译期无法确定大小
   |     |
   |     此调用引入的约束要求
   |
   = help: trait `Sized`未为`dyn MyTrait`实现
note: `C::<Allocator>::new`中的约束要求
  --> src/main.rs:39:6
   |
39 | impl<Allocator> C<Allocator>
   |      ^^^^^^^^^ 此约束在`C::<Allocator>::new`中要求
40 | where Allocator: MyTrait {
41 |     pub fn new(a: Box<Allocator>) -> Self {
   |            --- 此关联函数中的约束要求

更多错误信息请尝试`rustc --explain E0277`。
error: 无法编译playground(bin "playground"),因之前的错误

错误原因

你说的没错,Box<dyn MyTrait>本身是固定大小的(它本质是一个胖指针,占两个机器字长),但问题出在C::new的泛型约束上:

Rust的泛型参数默认会自动加上Sized约束,也就是要求类型在编译期大小确定。你的C结构体定义里虽然给Allocator加了+ ?Sized(允许它是大小不确定的类型),但impl块里的Allocator没有这个标记,所以new方法默认要求Allocator必须是Sized类型。

当你传入Box<dyn MyTrait>时,泛型参数Allocator会被推断为dyn MyTrait,而dyn MyTrait是大小不确定的(!Sized),不符合impl块的默认约束,于是报错。

解决办法

有两种简单的修改方式:

方法一:给impl块的泛型参数加上?Sized约束

修改C的impl块,让Allocator允许是大小不确定的类型:

impl<Allocator: ?Sized> C<Allocator>
where Allocator: MyTrait {
    pub fn new(a: Box<Allocator>) -> Self {
        Self { a }
    }
}

方法二:调用时显式指定类型参数

在调用C::new时,直接指定Allocator为dyn MyTrait,跳过自动推断:

C::<dyn MyTrait>::new(boxed_value);

推荐用第一种方法,这样C的new方法可以兼容所有符合MyTrait的类型,不管是Sized还是!Sized。

完整可编译代码

trait MyTrait {
    fn foo(&self);
}

struct A {}

impl MyTrait for A {
    fn foo(&self) {
        println!("A");
    }
}

struct B {}

impl MyTrait for B{
    fn foo(&self) {
        println!("B");
    }
}

enum MyEnum {
    A,
    B,
}

fn create_object(my_enum: MyEnum) -> Box<dyn MyTrait> {
    let boxed_value: Box<dyn MyTrait> = match my_enum {
        MyEnum::A => Box::new(A{}),
        MyEnum::B => Box::new(B{}),
    };
    boxed_value
}

struct C<Allocator>
where Allocator: MyTrait + ?Sized {
    a: Box<Allocator>,
}

impl<Allocator: ?Sized> C<Allocator>
where Allocator: MyTrait {
    pub fn new(a: Box<Allocator>) -> Self {
        Self { a }
    }
}


fn main() {
    let boxed_value = create_object(MyEnum::A);
    C::new(boxed_value);
}

内容的提问来源于stack exchange,提问作者JACK M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 19:17:08