The trait bound `&mut impl WriteAt + ?Sized: WriteAt` is not satisfied

I've implemented a WriteAt trait, that requires you to always give a position for the write.To work with the ecosystem I've created a CursorAt wrapper that implements Write:

pub struct CursorAt<T> {
    inner: T,
    position: u64,
}

impl<T> CursorAt<T> {
    pub fn new(inner: T, position: u64) -> Self {
        Self { inner, position }
    }
}

impl<T: WriteAt> Write for CursorAt<T> {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.inner.write_slice_at(&mut self.position, buf).unwrap();
        Ok(buf.len())
    }

    fn flush(&mut self) -> std::io::Result<()> {
        Ok(())
    }
}

When trying to use the CursorAt type with the flate2 crate:

fn compressed_to_file(writer: &mut (impl WriteAt + ?Sized), position: &mut u64) {
    let cursor = CursorAt::new(writer, *position);
    let mut encoder = ZlibEncoder::new(cursor, Compression::best());
    encoder.write_all(&file).unwrap();
    let cursor = encoder.finish().unwrap();
}

However the compiler tells me that WriteAt is not implemented for &mut impl WriteAt + ?Sized, which seems weird:

error[E0277]: the trait bound `&mut impl WriteAt + ?Sized: WriteAt` is not satisfied
   --> ubiart_toolkit/src/ipk/writer.rs:191:56
    |
191 |                     let mut encoder = ZlibEncoder::new(cursor, Compression::best());
    |                                       ---------------- ^^^^^^ the trait `WriteAt` is not implemented for `&mut impl WriteAt + ?Sized`, which is required by `CursorAt<&mut impl WriteAt + ?Sized>: std::io::Write`
    |                                       |
    |                                       required by a bound introduced by this call
    |
    = help: the following other types implement trait `WriteAt`:
              File
              std::vec::Vec<u8>
    = note: required for `CursorAt<&mut impl WriteAt + ?Sized>` to implement `std::io::Write`
note: required by a bound in `flate2::write::ZlibEncoder::<W>::new`
   --> flate2-1.0.28/src/zlib/write.rs:35:9
    |
35  | impl<W: Write> ZlibEncoder<W> {
    |         ^^^^^ required by this bound in `ZlibEncoder::<W>::new`
...
41  |     pub fn new(w: W, level: crate::Compression) -> ZlibEncoder<W> {
    |            --- required by a bound in this associated function

What can I do to fix this?

I've tried to implement WriteAt for &mut WriteAt but that loops forever and I can't figure out how to tell the compiler to use the write_slice_at from the &mut T:

impl<T: WriteAt + ?Sized> WriteAt for &mut T {
    fn write_slice_at(&mut self, position: &mut u64, buf: &[u8]) -> Result<(), WriteError> {
        self.write_slice_at(position, buf)
    }
}

P.S. This code is extracted from a much larger codebase, which is why it's a bit convoluted. The CursorAt type is also used to wrap my ReadAt implementation for Read, which is why the new function doesn't have trait bounds. I've also replaced some of the error handling with unwraps to make the code more compact.

(**self).write_slice_at(position, buf)

is what you want in the impl for &mut T.

2 Likes

Thank you! That works!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.