2

I have this signature that I wanna use in a Trait to create many adapters (file system, aws, google cloud etc.).

I'm trying to create the below Trait but this error occurs:

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

Why?

Fred Hors
  • 3,258
  • 3
  • 25
  • 71

1 Answers1

2

If you read your error message it will both mention that it's

...because method put_file has generic type parameters

as well as where you can find further info on object safety

You can just not create a trait object instead:

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

Or go with dynamic dispatch all the way:

async fn put_file(&self, filename: &str, stream: Box<dyn AsyncRead + Unpin + Send>) -> Result<()>;
cafce25
  • 15,907
  • 4
  • 25
  • 31