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

Rust actix-web使用自定义trait作为app_data报Sized未实现错误如何解决

错误根因

两个报错都是围绕dyn AsyncKeyProvider是动态大小类型(DST)、不满足Sized约束导致的:

  1. Arc::new要求传入的参数是编译期大小确定的Sized类型,你不能直接用它构造trait对象,需要先构造具体类型的Arc再通过unsized coercion转换为trait对象的Arc
  2. actix_web::web::Data的into_inner()方法要求内层的T满足Sized约束,因为它要转移内部Arc<T>的所有权,动态大小的trait对象不满足这个约束,所以无法调用该方法。

可行解决方案

方案1:保留多态特性,直接调用trait方法(最常用)

如果你不需要拿到GoogleKeyProvider的具体实例,只是要调用AsyncKeyProvider trait定义的方法,完全不需要调用into_inner,web::Data本身实现了Deref trait,可以直接调用trait的方法。
首先修正初始化代码的类型转换写法:

// 先初始化具体的GoogleKeyProvider实例
let google_provider = GoogleKeyProvider {
    cached: None,
    expiration_time: Instant::now(),
};
// 先构造具体类型的Arc,再显式转换为trait对象的Arc,最后包成web::Data
let key_provider: web::Data<dyn AsyncKeyProvider> = web::Data::from(
    Arc::new(google_provider) as Arc<dyn AsyncKeyProvider>
);

然后在validate函数中直接调用方法即可,不需要into_inner:

pub async fn validate(jwt_body: web::Json<JwtBody>, provider: web::Data<dyn AsyncKeyProvider>) -> impl Responder {
    // 直接通过provider调用trait方法即可,不需要取内层实例
    let key = provider.get_key_async(&jwt_body.key_id).await;
    // 后续业务逻辑
}

方案2:直接存储具体类型(适合无需多态的场景)

如果你只有GoogleKeyProvider这一种密钥提供器实现,不需要多态切换不同的实现,可以直接存储具体类型的实例,就可以正常调用into_inner了:
初始化代码修改为:

let google_provider = GoogleKeyProvider {
    cached: None,
    expiration_time: Instant::now(),
};
let key_provider = web::Data::new(google_provider);

对应的validate函数参数修改为具体类型:

pub async fn validate(jwt_body: web::Json<JwtBody>, provider: web::Data<GoogleKeyProvider>) -> impl Responder {
    // 此时可以正常调用into_inner,因为GoogleKeyProvider是Sized类型
    let provider_object = provider.into_inner();
    // 后续业务逻辑
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 02:03:04