Search code examples
rusttraits

How do I implement a trait I don't own for a type I don't own?


I wanted to implement the Shl trait for Vec, the code is below. This would make things like vec << 4 possible, which would be nice sugar for vec.push(4).

use std::ops::Shl;

impl<T> Shl<T> for Vec<T> {
    type Output = Vec<T>;

    fn shl(&self, elem: &T) -> Vec<T> {
        self.push(*elem);
        *self
    }
}

fn main() {
    let v = vec![1, 2, 3];
    v << 4;
}

The compilation fails with the following error:

cannot provide an extension implementation where both trait and type are not defined in this crate [E0117]

or

type parameter T must be used as the type parameter for some local type (e.g. MyStruct<T>); only traits defined in the current crate can be implemented for a type parameter [E0210]

As I understand it, I'd have to patch the stdlib, more specifically the collections::vec crate. Is there another way to change this code to compile successfully?


Solution

  • While you can't do that exactly, the usual workaround is to just wrap the type you want in your own type and implement the trait on that.

    use somecrate::FooType;
    use somecrate::BarTrait;
    
    struct MyType(FooType);
    
    impl BarTrait for MyType {
        fn bar(&self) {
            // use `self.0` here
        }
    }