
Хозяйке на заметку
Если вы когда-нибудь писали на Rust какую-нибудь рекурсивную структуру, то у вас там наверняка было поле вроде
Option<Box<Self>>
или Option<Rc<Self>>
. Для обхода подобной структуры требуется получить ссылку из поля такого типа. В принципе, можно писать что-то вродеif let Some(relative) = &self.relative {, но если по каким-то причинам требуется
// здесь можно работать с relative как с &Self благодаря deref coercion
}
Option<&Self>
, то это уже не сработает из-за несовпадения типов. Приведение типов в подобной ситуации выглядит как field.as_ref().map(<_>::deref)
, или того хуже, field.as_ref().map(|x| &**x)
. Как я недавно с некоторым удивлением для себя обнаружил, это достаточно распространённый паттерн, чтобы для него были отдельные методы: Option::as_deref и Option::as_deref_mut. Что они делают — очевидно по типам:fn as_deref(&self) -> Option<&<T as Deref>::Target>;Есть резон не использовать эти методы? Если у вас стоит задача поддерживать старые версии rustc, то да, есть: эти методы были добавлены в Rust 1.40.0 (видимо, по этой причине я раньше про них и не знал). Конечно, ничто не мешает написать extension trait для добавления этих методов, только имейте в виду: если одно и то же выражение может быть как вызовом собственного метода типа, так и вызовом метода трейта, то предпочтение всегда отдаётся собственному методу типа.
fn as_deref_mut(&mut self) -> Option<&mut <T as Deref>::Target>;