'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
Tmust 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 1:[1]
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
}
}
Solution 2:[2]
This would make things like
vec << 4possible, which would be nice sugar forvec.push(4).
Although it can be done, it is generally a bad idea to implement an operator with a unexpected semantic.
Here is an example of how this can be done:
use std::ops::Shl;
struct BadVec<T>(Vec<T>);
impl<T> Shl<T> for BadVec<T> {
type Output = BadVec<T>;
fn shl(mut self, elem: T) -> Self::Output {
self.0.push(elem);
self
}
}
fn main() {
let mut v = BadVec(vec![1, 2, 3]);
v = v << 4;
assert_eq!(vec![1, 2, 3, 4], v.0)
}
If you implement Deref (DerefMut):
use std::ops::{Deref, DerefMut};
impl<T> Deref for BadVec<T> {
type Target = Vec<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for BadVec<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
you can call Vec methods:
fn main() {
let mut v = BadVec(vec![1, 2, 3]);
v = v << 4;
v.truncate(2);
assert_eq!(2, v.len());
}
Take a look at the newtype_derive crate, it can generate some boilerplate code for you.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Shepmaster |
| Solution 2 |
