Weird trait/implementation error

Playground

The code:
trait FooElem: Sized {}

trait FooExt<T: FooElem>: Sized {
    fn do_stuff(&mut self);
}

impl<T: FooElem, E: ExactSizeIterator<Item=T>> FooExt<T> for E {
    fn do_stuff(&mut self) {
        //empty
    }
} 

trait Bar {
    fn barred(&mut self);
}

impl<T: FooElem> Bar for Vec<T> {
    fn barred(&mut self) {
        FooExt::do_stuff(&mut self.into_iter())
    }
}

I get the error:

error[E0277]: the trait bound `&mut T: FooElem` is not satisfied
  --> src/main.rs:21:9
   |
21 |         FooExt::do_stuff(&mut self.into_iter())
   |         ^^^^^^^^^^^^^^^^ the trait `FooElem` is not implemented for `&mut T`
   |
   = note: required because of the requirements on the impl of `FooExt<&mut T>` for `std::slice::IterMut<'_, T>`
note: required by `FooExt::do_stuff`
  --> src/main.rs:6:5
   |
6  |     fn do_stuff(&mut self);
   |     ^^^^^^^^^^^^^^^^^^^^^^^

Any ideas to help?

The compiler tells you the problem:

The most literal solution is to require that a mutable reference implements the trait:

impl Bar for Vec<T>
where
    for<'b> &'b mut T: FooElem,
{

Your 'a is unneeded.


I'd also write it as

impl<I> FooExt<I::Item> for I
where
    I: ExactSizeIterator,
    I::Item: FooElem,
{
    fn do_stuff(&mut self) {
        //empty
    }
}

Note that the type of self is &mut Vec<T>. Calling into_iter() on that gets you an iterator over &mut T items, just like if you'd called Vec::iter_mut(). Then your FooExt implementation is demanding that these &mut T items must implement FooElem, which they do not -- only T does.

If you wanted to move the actual T items out of the Vec, then drain() might work better.

1 Like

Yep. Or you could change your trait to accept self:

trait FooElem {}

trait FooExt<T>
where
    T: FooElem,
{
    fn do_stuff(self);
}

impl<I> FooExt<I::Item> for I
where
    I: ExactSizeIterator,
    I::Item: FooElem,
{
    fn do_stuff(self) {
        //empty
    }
}

trait Bar {
    fn barred(self);
}

impl<T> Bar for Vec<T>
where
    T: FooElem,
{
    fn barred(self) {
        FooExt::do_stuff(self.into_iter())
    }
}

And implement your trait for both direct values as well as references to values.