Я пишу будущий комбинатор, который должен использовать значение, которое ему было предоставлено. С фьючерсами 0.1 Future::poll
взял self: &mut Self
, что фактически означало, что мой комбинатор содержал Option
и я вызвал Option::take
on, когда базовое будущее разрешается.
Вместо этого метод Future::poll
в стандартной библиотеке принимает self: Pin<&mut Self>
, поэтому я читал о гарантиях, необходимых для безопасного использования Pin
.
Из документации по pin
модулю на гарантию Drop
(выделено мое):
Конкретно, для закрепленных данных вы должны поддерживать инвариант, чтобы его память не становилась недействительной с момента, когда она закреплена, до момента вызова drop. Память может быть аннулирована путем освобождения, но также путем замены
Some(v)
наNone
или вызоваVec::set_len
чтобы "убить" некоторые элементы из вектора.
И проекции и структурное закрепление (выделено мной):
Вы не должны предлагать какие-либо другие операции, которые могут привести к удалению данных из полей при закреплении вашего типа. Например, если обертка содержит
Option<T>
и есть операция типа like с типомfn(Pin<&mut Wrapper<T>>) → Option<T>
, эту операцию можно использовать для перемещенияT
из закрепленногоWrapper<T>
- это означает, что закрепление не может быть структурным.
Однако существующий комбинатор Map
вызывает Option::take
значение элемента, когда базовое будущее разрешено:
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
match self.as_mut().future().poll(cx) {
Poll::Pending => Poll::Pending,
Poll::Ready(output) => {
let f = self.f().take()
.expect("Map must not be polled after it returned 'Poll::Ready'");
Poll::Ready(f(output))
}
}
}
Метод f
генерируется unsafe_unpinned
и выглядит примерно так:
fn f<'a>(self: Pin<&'a mut Self>) -> &'a mut Option<F> {
unsafe { &mut Pin::get_unchecked_mut(self).f }
}
Похоже, что Map
нарушает требования, описанные в документации по pin
, но я считаю, что авторы комбинатора Map
знают, что они делают, и что этот код безопасен.
Какая логика позволяет им выполнять эту операцию безопасным способом?