In Rust, è consentito implementare un trait per un tipo solo se:
Queste condizioni sono chiamate orphan rule (regola "orfana"). Ciò protegge dai conflitti in caso di implementazioni indipendenti dello stesso trait per lo stesso tipo in diversi crate.
Se desideri implementare un trait esterno per un tipo esterno, non è possibile farlo direttamente. Di solito si utilizza il pattern "newtype": avvolgere il tipo in una struttura propria all'interno del crate e poi implementare il trait per il proprio tipo.
Esempio:
// Tipo esterno e trait esterno (non nel nostro crate) // struct ExternalType; trait ExternalTrait { ... } struct MyWrapper(ExternalType); impl ExternalTrait for MyWrapper { /* ... */ } // Ora lavoriamo attraverso l'involucro
Domanda: È possibile implementare un trait esterno per un tipo esterno, se entrambi sono pubblici, tramite use e impl?
Risposta errata: Sì, basta semplicemente dichiarare impl nel proprio crate e tutto funzionerà.
Risposta corretta: No, il compilatore non lo consentirà. È possibile implementare un trait solo se il trait o il tipo sono dichiarati nel crate attuale. In caso contrario, si verifica un errore della orphan rule.
Esempio di errore:
// extern crate other; // impl Display for other::ExternalType { ... } // Errore orphan rule
Storia
Nel team è stata necessaria la supporto di un logger esterno tramite impl di un trait esterno. Il tentativo di implementarlo per un tipo di terze parti ha portato a un errore della orphan rule e a lunghe discussioni sulle cause. Alla fine, è stato necessario riprogettare l'architettura secondo il newtype.
Storia
In un progetto open-source, si è deciso di implementare Debug per una struttura di un'altra libreria, cosa che non ha permesso la orphan rule. Di conseguenza, gli utenti sono stati costretti a lavorare con workaround scomodi e a scrivere le proprie involucri.
Storia
Grave bug: nel tentativo di implementare FromStr per un enum esterno per l'analisi da stringa, il compilatore ha bloccato la orphan rule. Lo sviluppatore ha "risolto" il problema tramite conversioni unsafe in memoria, il che ha portato a UB in produzione.