rust 为什么此特征无效?使用什么签名代替?[duplicate]

7kqas0il  于 2022-12-19  发布在  其他
关注(0)|答案(1)|浏览(125)
    • 此问题在此处已有答案**:

Why are trait methods with generic type parameters object-unsafe?(2个答案)
6天前关闭。
我有这个签名,我想用在一个特质,以创建许多适配器(文件系统,aws,谷歌云等)。
我尝试创建下面的Trait,但出现此错误:

use tokio::io::AsyncRead;

#[async_trait::async_trait]
pub trait Trait: Send + Sync {
    async fn put_file<S>(&self, filename: &str, stream: S) -> Result<()>
    where
        S: AsyncRead + Send;
}

pub struct Client {
    location: String,
}

#[async_trait::async_trait]
impl Trait for Client {
    async fn put_file<S>(&self, filename: &str, stream: S) -> Result<()>
    where
        S: AsyncRead + Send,
    {
        futures::pin_mut!(stream);

        let path = Path::new(&self.location).join(filename);

        let mut file = BufWriter::new(File::create(path).await?);

        tokio::io::copy(&mut stream, &mut file).await?;

        Ok(())
    }
}
error[E0038]: the trait `Trait` cannot be made into an object
   |
23 |     pub client: Arc<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>
   |
5  | pub trait Trait: Send + Sync {
   |           ----- this trait cannot be made into an object...
6  |     async fn put_file<S>(&self, filename: &str, stream: S) -> Result<()>
   |              ^^^^^^^^ ...because method `put_file` has generic type parameters
   = help: consider moving `put_file` to another trait

为什么?

2hh7jdfx

2hh7jdfx1#

如果您阅读错误消息,它会提到
...因为方法put_file具有泛型类型参数
以及您可以在何处找到有关对象安全性的更多信息
你可以不创建trait对象:

struct YourStructThatContainsTrait<T: Trait> {
    pub client: Arc<T>,
}

或者全程使用动态调度:

async fn put_file(&self, filename: &str, stream: Box<dyn AsyncRead + Unpin + Send>) -> Result<()>;

相关问题