Trait of Map<Iter> without Copy

I have a somewhat basic trait

trait Dup<T> {
    fn dup(&mut self) -> Vec<T>;
}

with an implementation to "duplicate" element. For example:

impl<'a, F, T> Dup<T> for Map<Iter<'a, T>, F>
    where F: FnMut(&'a T) -> T,
    T: Clone
{
    fn dup(&mut self) -> Vec<T> {
        let mut tot = vec![];

        for int in self {
            tot.push(int.clone());
            tot.push(int);
        }

        tot
    }
}

It can easily be used like that:

    let ints = vec![1, 2]
        .iter()
        .map(|e| e + 1)
        .dup(); // [2, 2, 3, 3]

which is the expected result.
But for some reason, it seams that when there is an object that doesn't implements Copy, this doesnt work anymore.

    let strings = vec![String::new()]
        .iter()
        .map(|e| e)
        .dup(); // PANICS

with the following error:

error[E0599]: the method `dup` exists for struct `Map<Iter<'_, String>, ...>`, but its trait bounds were not satisfied
  --> src/main.rs:35:10
   |
32 |       let strings = vec![String::new()]
   |  ___________________-
33 | |         .iter()
34 | |         .map(|e| e)
   | |              --- doesn't satisfy `<_ as FnOnce<(&String,)>>::Output = String`
35 | |         .dup();
   | |         -^^^ method cannot be called on `Map<Iter<'_, String>, ...>` due to unsatisfied trait bounds
   | |_________|
   |
   |
  ::: /home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/adapters/map.rs:62:1
   |
62 |   pub struct Map<I, F> {
   |   -------------------- doesn't satisfy `_: Dup<String>`
   |

The error seems a bit mysterious to me, and even tho I tried multiple times to fix it, I can't really find a way of doing so. It's probably something like "String doesnt implements Copy" problem, but I would like it to work without Copy.
Does someone has a clue to do that ?

Your implementation is only for maps over slice iterators whose closure takes a &T and outputs a T.

    where F: FnMut(&'a T) -> T,

The failing one takes a &T and returns a &T. That would be

    where F: FnMut(&'a T) -> &'a T,

But IMO the actual solution is to make the implementation more generic -- there's no reason for you to care about the specific iterator as far as I can see. (A map with a specific signature over a slice iterator is a very specific type.)

impl<I, T> Dup<T> for I
where
    I: ?Sized + Iterator<Item = T>,
    T: Clone,

Note that your String example will result in a Vec<&String>. You can use the .cloned() adapter to get a Vec<String> instead.

This could also be implemented as an iterator adaptor of your own instead of returning a collected Vec<T>.

Side note, compilation failures and panics are different things.

2 Likes

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.