¿Cómo implemento un rasgo que no poseo para un tipo que no soy de mi propiedad?

Quería implementar el rasgo Shl para Vec , el código está debajo. Esto haría posibles cosas como vec << 4 , que sería una buena azúcar para vec.push(4) .

 use std::ops::Shl; impl Shl for Vec { type Output = Vec; fn shl(&self, elem: &T) -> Vec { self.push(*elem); *self } } fn main() { let v = vec![1, 2, 3]; v << 4; } 

La comstackción falla con el siguiente error:

no puede proporcionar una implementación de extensión donde tanto el rasgo como el tipo no están definidos en esta caja [E0117]

o

el parámetro de tipo T debe usar como parámetro de tipo para algún tipo local (por ejemplo, MyStruct ); solo los rasgos definidos en la caja actual pueden implementarse para un parámetro de tipo [E0210]

Según lo entiendo, tendré que parchear el stdlib, más específicamente el collections::vec crate. ¿Hay alguna otra forma de cambiar este código para comstackr con éxito?

Si bien no puede hacer eso exactamente, la solución habitual es simplemente ajustar el tipo que desee en su propio tipo e implementar el rasgo en eso.

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

Esto haría posibles cosas como vec < < 4 , que sería una buena azúcar para vec.push(4) .

Aunque se puede hacer, generalmente es una mala idea implementar un operador con una semántica inesperada.

Aquí hay un ejemplo de cómo se puede hacer esto:

 use std::ops::Shl; struct BadVec(Vec); impl Shl for BadVec { type Output = BadVec; 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) } 

Si implementa Deref ( DerefMut ):

 use std::ops::{Deref, DerefMut}; impl Deref for BadVec { type Target = Vec; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for BadVec { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } 

puedes llamar a los métodos de Vec :

 fn main() { let mut v = BadVec(vec![1, 2, 3]); v = v < < 4; v.truncate(2); assert_eq!(2, v.len()); } 

Eche un vistazo a newtype_derive , puede generar un código repetitivo para usted.