En Rust, se permite implementar un trait para un tipo solo si:
Estas condiciones se conocen como regla de orfanato (orphan rule). Esto protege contra conflictos en caso de implementaciones independientes del mismo trait para el mismo tipo en diferentes crates.
Si desea implementar un trait externo para un tipo externo, no es posible hacerlo directamente. Normalmente se utiliza el patrón "newtype": envolver el tipo en su propia estructura dentro del crate, y luego implementar el trait para su propio tipo.
Ejemplo:
// Tipo externo y trait externo (no en nuestro crate) // struct ExternalType; trait ExternalTrait { ... } struct MyWrapper(ExternalType); impl ExternalTrait for MyWrapper { /* ... */ } // Ahora trabajamos a través de la envoltura
Pregunta: ¿Se puede implementar un trait externo para un tipo externo, si ambos son públicos, a través de use e impl?
Respuesta incorrecta: Sí, solo es necesario declarar impl en su crate y todo funcionará.
Respuesta correcta: No, el compilador no lo permitirá. Solo se permite implementar un trait si el trait o el tipo están declarados en el crate actual. En caso contrario, se producirá un error de regla de orfanato.
Ejemplo de error:
// extern crate other; // impl Display for other::ExternalType { ... } // Error de regla de orfanato
Historia
En el equipo se necesitaba soporte para un logger externo a través de impl de un trait externo. Intentar implementarlo para un tipo ajeno llevó a un error de regla de orfanato y prolongados debates sobre las razones. Al final, hubo que rehacer la arquitectura para usar newtype.
Historia
En un proyecto de código abierto decidieron implementar Debug para una estructura de otra biblioteca, lo que no permitió la regla de orfanato. Como resultado, los usuarios se vieron obligados a trabajar con soluciones incómodas y escribir sus propias envolturas.
Historia
Un error grave: al intentar implementar FromStr para un enum externo para el análisis desde una cadena, el compilador no pasó la regla de orfanato. El desarrollador "solucionó" el problema a través de conversiones inseguras en memoria, lo que provocó UB en producción.