ProgrammatieRust ontwikkelaar, API/Library ontwerper

Leg uit hoe het systeem van traits in Rust werkt bij het werken met externe typen (weesregel). Hoe implementeer je een trait voor een type dat je niet hebt gedeclareerd, en waarom is dit niet altijd mogelijk?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

In Rust is het toegestaan om een trait voor een type te implementeren alleen als:

  • de trait is gedeclareerd in de huidige crate OF
  • het type is gedeclareerd in de huidige crate

Deze voorwaarden worden de weesregel (orphan rule) genoemd. Dit beschermt tegen conflicten in het geval van onafhankelijke implementaties van dezelfde trait voor hetzelfde type in verschillende crates.

Als je een externe trait voor een extern type wilt implementeren - is dat direct niet mogelijk. Gewoonlijk wordt het patroon van "newtype" gebruikt: het type in een eigen structuur binnen de crate verpakken en vervolgens de trait voor je eigen type implementeren.

Voorbeeld:

// Extern type en externe trait (niet in onze crate) // struct ExternalType; trait ExternalTrait { ... } struct MyWrapper(ExternalType); impl ExternalTrait for MyWrapper { /* ... */ } // Nu werken we via de wrapper

Vraag met een valstrik

Vraag: Kun je een externe trait voor een extern type implementeren als beiden openbaar zijn, via use en impl?

Onjuiste antwoord: Ja, het is voldoende om gewoon de impl in je eigen crate te verklaren, en alles zal werken.

Juiste antwoord: Nee, de compiler zal dat niet toestaan. Het is alleen toegestaan om een trait te implementeren als de trait of het type is gedeclareerd in de huidige crate. Anders is er een weesregel fout.

Voorbeeld foutmelding:

// extern crate other; // impl Display for other::ExternalType { ... } // Fout weesregel

Voorbeelden van echte fouten door onwetendheid over de fijne kneepjes van het onderwerp


Verhaal

Het team had ondersteuning nodig voor een externe logger via impl van een externe trait. Pogingen om deze voor een extern type te implementeren leidde tot een weesregel fout en lange discussies over de oorzaken. Uiteindelijk moest de architectuur worden herontworpen naar newtype.


Verhaal

In een open-source project besloten ze om Debug te implementeren voor een structuur uit een andere bibliotheek, wat niet mogelijk was door de weesregel. Als gevolg hiervan waren gebruikers gedwongen om te werken met onhandige workarounds en hun eigen wrappers te schrijven.


Verhaal

Ernstige bug: bij de poging om FromStr voor een extern enum voor het parseren van een string te implementeren, stond de compiler de weesregel niet toe. De ontwikkelaar "oplosste" het probleem via unsafe geheugenmanipulaties, wat leidde tot UB in productie.