В Rust реализовать trait для типа разрешается только если:
Эти условия называются orphan rule (правило "сироты"). Это защищает от конфликтов в случае независимых внедрений одного и того же trait для одного и того же типа в разных crate.
Если вы хотите реализовать внешний trait для внешнего типа — напрямую это невозможно. Обычно используется pattern "newtype": обернуть тип в свою структуру внутри crate, а затем реализовать trait для собственного типа.
Пример:
// Внешний тип и внешний trait (не в нашем crate) // struct ExternalType; trait ExternalTrait { ... } struct MyWrapper(ExternalType); impl ExternalTrait for MyWrapper { /* ... */ } // Теперь работаем через обертку
Вопрос: Можно ли реализовать внешний trait для внешнего типа, если оба публичные, через use и impl?
Неверный ответ: Да, достаточно просто объявить impl в своем crate, и все будет работать.
Правильный ответ: Нет, такое компилятор не разрешит. Разрешается реализовать trait только если trait или тип объявлены в текущем crate. В противном случае — orphan rule error.
Пример ошибки:
// extern crate other; // impl Display for other::ExternalType { ... } // Ошибка orphan rule
История
В команде понадобилась поддержка внешнего логгера через impl внешнего trait. Попытка реализовать его для стороннего типа привела к ошибке orphan rule и долгим спорам о причинах. В итоге пришлось переделывать архитектуру под newtype.
История
В open-source проекте решили реализовать Debug для структуры из другой библиотеки, что не позволила orphan rule. В результате пользователи вынуждены были работать с неудобными workarounds и писать свои обертки.
История
Серьёзный баг: при попытке реализовать FromStr для внешнего enum для разбора из строки компилятор не пропустил orphan rule. Разработчик "решил" проблему через unsafe-преобразования по памяти, что вызвало UB на production.