'Mismatched types' in impl when attempting to make parameter borrowed

Error message:

error[E0308]: mismatched types
  --> src/message/func.rs:14:19
   |
9  | impl<T> VecWithHardLimit<T> for Vec<T> {
   |      - expected this type parameter
...
14 |         self.push(element.clone());
   |              ---- ^^^^^^^^^^^^^^^ expected type parameter `T`, found `&T`
   |              |
   |              arguments to this method are incorrect
   |
   = note: expected type parameter `_`
                   found reference `&_`
note: `T` does not implement `Clone`, so `&T` was cloned instead
  --> src/message/func.rs:14:19
   |
14 |         self.push(element.clone());
   |                   ^^^^^^^
note: method defined here
  --> /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/alloc/src/vec/mod.rs:1915:12

Code:

pub trait VecWithHardLimit<T> {
    fn push_with_hard_limit(&mut self, element: &T);
}

impl<T> VecWithHardLimit<T> for Vec<T> {
    fn push_with_hard_limit(&mut self, element: &T) {
        if self.len() == self.capacity() {
            self.remove(0); // Remove the oldest element
        }
        self.push(element.clone());
    }
}

This is just run with vector.push_with_hard_limit("test");
Why do I get this error? It said I should borrow in an earlier error message, but when trying to borrow like this, it doesn't work? Is there a separate step I should be taking? Does another type parameter need to be changed? Any help would be nice, thanks!

You're calling element.clone(), but you haven't specified a bound of T: Clone, so T doesn't visibly implement Clone. When that happens, method lookup tries auto-referencing to find a method named “clone”, with the result that it ends up calling the implementation of Clone on &T — giving you a cloned reference, which doesn't help.

To fix the compilation error, add a Clone bound:

impl<T: Clone> VecWithHardLimit<T> for Vec<T> {

However, methods generally shouldn't take references that they always have to clone values from, since that's inefficient. That is, push_with_hard_limit() should take element: T, not element: &T. You said

It said I should borrow in an earlier error message

Can you show us that error? Not just what the compiler suggested (suggestions are sometimes wrong because the compiler doesn't know what you're trying to do), but the full text of the error message.


Also, Vec::remove() is a slow operation as you are using it, every push_with_hard_limit() that is at capacity will have to move all the other items, individually. For this purpose you should use a VecDeque which can remove items from either end cheaply.