Search code examples
rusttraits

error: the trait bound `someStruct<std::fs::File>: Write<std::fs::File>` is not satisfied


I am trying to create a generic wrapper type to simplify so branching logic however the compiler complains that the Write trait is not implemented for the specific type being used in that function.

Not pictured here is the logic of someFunction requires the inner type to do some instructions specific to itself to finish it's task. Seeing as I can't implement a trait to do so on the third-party struct, I am creating a wrapper so that I can implement a new trait that will serve as a cleanup step at the end of someFunction.

pub struct someWrapper<T>
where T: Write
{
    inner: someInnerStuct<T>
}

impl<T: Write> someWrapper<T>
where T: Write
{
    fn flush(&mut self) -> io::Result<()> {
        self.inner.flush()
    }

    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.inner.write(buf)
    }
}

fn buildStruct<T>(input: T) -> someWrapper<T>
where T: Write
{
    someWrapper{
        inner: someInnerStuct::new(input)
    }
}

fn someFunction<T: 'static>(
    func: fn(fs::File) -> T
) -> io::Result<()> 
where T: Write
{
    ...
}

fn main()
{
    someFunction(buildStruct);
}

I have no idea how to fix this because as far as I can see that trait bound has been satisfied for any type that implements Write.

Implementing the Write trait explicitly solves the problem but defeats the purpose of making it generic no?


Solution

  • You never actually implement Write on someWrapper. You instead just add bounds to T saying that someWrapper can only every contain something that is Write.

    The simplest implementation would be

    impl<T> Write for someWrapper<T> where T: Write
    {
        fn flush(&mut self) -> io::Result<()> {
            self.inner.flush()
        }
    
        fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
            self.inner.write(buf)
        }
    }
    

    Which you very nearly had. In your impl block you bound T to be Write twice. Once in the <T: Write>, once in the where clause. Just one will do.

    This change also necessitates changing your struct declaration to

    pub struct someWrapper<T> where T: Write
    {
        inner: T
    }
    

    as I do not know what someInnerStuct is.

    Also to note, you do not need the bounds on someWrapper's struct declaration. The following is sufficient.

    pub struct someWrapper<T>
    {
        inner: T
    }
    

    The impl block for Write still works to make someWrapper: Write if T: Write. But otherwise will let you stick anything in someWrapper.