En Rust, il est permis de réaliser un trait pour un type uniquement si :
Ces conditions sont appelées la règle des orphelins. Cela protège contre les conflits en cas d'implémentations indépendantes du même trait pour le même type dans différents crates.
Si vous souhaitez implémenter un trait externe pour un type externe, cela n'est pas possible directement. On utilise généralement le motif "newtype" : envelopper le type dans votre propre structure à l'intérieur du crate, puis implémenter le trait pour votre propre type.
Exemple :
// Type externe et trait externe (non dans notre crate) // struct ExternalType; trait ExternalTrait { ... } struct MyWrapper(ExternalType); impl ExternalTrait for MyWrapper { /* ... */ } // Maintenant, nous travaillons à travers la wrapper
Question : Peut-on implémenter un trait externe pour un type externe, si les deux sont publics, à l'aide de use et impl ?
Réponse incorrecte : Oui, il suffit juste de déclarer impl dans son crate, et tout fonctionnera.
Réponse correcte : Non, le compilateur ne le permettra pas. Il est permis d'implémenter un trait uniquement si le trait ou le type sont déclarés dans le crate actuel. Sinon, cela entraîne une erreur de règle des orphelins.
Exemple d'erreur :
// extern crate other; // impl Display for other::ExternalType { ... } // Erreur de règle des orphelins
Histoire
L'équipe avait besoin d'un support de logger externe via impl d'un trait externe. La tentative de l'implémenter pour un type tiers a conduit à une erreur de règle des orphelins et à de longues discussions sur les raisons. En fin de compte, il a fallu réviser l'architecture selon le motif newtype.
Histoire
Dans un projet open-source, ils ont décidé d'implémenter Debug pour une structure d'une autre bibliothèque, ce que la règle des orphelins n'a pas permis. En conséquence, les utilisateurs ont dû travailler avec des solutions de contournement peu pratiques et écrire leurs propres wrappers.
Histoire
Bug sérieux : en essayant d'implémenter FromStr pour un enum externe afin d'analyser à partir d'une chaîne, le compilateur a bloqué la règle des orphelins. Le développeur a "résolu" le problème par des transformations unsafe en mémoire, ce qui a entraîné un comportement indéfini en production.