什么时候可以将会员价值从固定的未来中转移出来? [英] When is it safe to move a member value out of a pinned future?
问题描述
我正在编写一个将来的组合器,该组合器需要使用它提供的值.对于期货0.1, Future::poll
取了self: &mut Self
,这实际上意味着我的组合器包含一个Option
,并且在潜在的未来结算时我在其上调用了Option::take
.
I'm writing a future combinator that needs to consume a value that it was provided with. With futures 0.1, Future::poll
took self: &mut Self
, which effectively meant that my combinator contained an Option
and I called Option::take
on it when the underlying future resolves.
Future::poll
标准库中的方法取而代之的是self: Pin<&mut Self>
,因此我一直在阅读有关安全使用Pin
所需的保证的信息.
The Future::poll
method in the standard library takes self: Pin<&mut Self>
instead, so I've been reading about the guarantees required in order to safely make use of Pin
.
从 Drop
保证(强调我的意思):
From the pin
module documentation on the Drop
guarantee (emphasis mine):
具体而言,对于固定的数据,您必须保持不变,即从固定到调用drop为止,其内存不会失效.可以通过释放来使内存无效,也可以通过用
None
替换Some(v)
或调用Vec::set_len
从向量中杀死"某些元素来使内存无效.
Concretely, for pinned data you have to maintain the invariant that its memory will not get invalidated from the moment it gets pinned until when drop is called. Memory can be invalidated by deallocation, but also by replacing a
Some(v)
byNone
, or callingVec::set_len
to "kill" some elements off of a vector.
投影和结构固定(重点是我的):
在固定类型时,您不得提供任何其他可能导致数据从字段中移出的操作.例如,如果包装器包含
Option<T>
,并且存在类型为fn(Pin<&mut Wrapper<T>>) -> Option<T>
的仿冒操作,则可以使用该操作将T
从固定的Wrapper<T>
中移出-这意味着固定不可能是结构性的.
You must not offer any other operations that could lead to data being moved out of the fields when your type is pinned. For example, if the wrapper contains an
Option<T>
and there is a take-like operation with typefn(Pin<&mut Wrapper<T>>) -> Option<T>
, that operation can be used to move aT
out of a pinnedWrapper<T>
-- which means pinning cannot be structural.
但是,现有的
The 似乎 It appears that 什么逻辑允许他们安全地执行此操作? What logic allows them to perform this operation in a safe manner? 这全部与结构钉扎有关. It is all about structural pinning. 首先,我将使用语法 First, I will use the syntax 假设我们有: 最初的问题是 是否可以通过将 Can we get a 这需要基本投影 This requires the basic projection 共享引用( 唯一引用( 对于这种类型的投影,我将使用语法 I will use the syntax 问题现在变成: 我们可以从 从文档中可能不清楚的一点是,这取决于 The point that may be unclear from the documentation is that it is up to the creator of 对于每个结构字段,库作者有两种可能的选择. There are two possible choices for the library author for each struct field. 例如, 要使 仅当具有结构化 the whole struct must only implement 仅当 the whole struct may only implement 结构不能为 the struct cannot be In your given 例如, 在这种情况下,该字段不会被 In this case, that field is not considered pinned by a In your given 这篇关于什么时候可以将会员价值从固定的未来中转移出来?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!f
方法由 unsafe_unpinned
宏,其外观大致类似于:f
method is generated by the unsafe_unpinned
macro and looks roughly like:fn f<'a>(self: Pin<&'a mut Self>) -> &'a mut Option<F> {
unsafe { &mut Pin::get_unchecked_mut(self).f }
}
Map
违反了pin
文档中描述的要求,但是我相信Map
组合器的作者知道他们在做什么,并且该代码是安全的.Map
violates the requirements that are described in the pin
documentation, but I believe that the authors of the Map
combinator know what they are doing and that this code is safe.推荐答案
P<T>
来表示类似impl Deref<Target = T>
的东西-某些(智能)指针类型P
,其将Deref::deref
指向T
. Pin
仅对此类(智能)指针应用"/有意义.P<T>
to mean something like impl Deref<Target = T>
— some (smart) pointer type P
that Deref::deref
s to a T
. Pin
only "applies" to / makes sense on such (smart) pointers.struct Wrapper<Field> {
field: Field,
}
Pin<P<_>>
从Wrapper
投射到其field
来从Pin<P<Wrapper<Field>>>
中获得Pin<P<Field>>
?
Pin<P<Field>>
from a Pin<P<Wrapper<Field>>>
, by "projecting" our Pin<P<_>>
from the Wrapper
to its field
?P<Wrapper<Field>> -> P<Field>
,这仅适用于:P<Wrapper<Field>> -> P<Field>
, which is only possible for:
P<T> = &T
).鉴于Pin<P<T>>
始终 deref
s到T
.P<T> = &mut T
).&[mut] T
.&[mut] T
for this type of projection.
Pin<&[mut] Wrapper<Field>>
转到Pin<&[mut] Field>
吗?Wrapper
的创建者!Wrapper
to decide!pin_utils::unsafe_pinned!
宏用于定义此类投影(Pin<&mut Wrapper<Field>> -> Pin<&mut Field>
).Pin
投影更声音:
Pin
投影的所有字段都实现Unpin
时,整个结构才必须实现Unpin
.
Unpin
when all the fields for which there is a structural Pin
projection implement Unpin
.
unsafe
将此类字段移出Pin<&mut Wrapper<Field>>
(或在Self = Wrapper<Field>
时为Pin<&mut Self>
).例如, Option::take()
被禁止.
unsafe
to move such fields out of a Pin<&mut Wrapper<Field>>
(or Pin<&mut Self>
when Self = Wrapper<Field>
). For instance, Option::take()
is forbidden.Drop::drop
不移动任何具有结构投影的字段时,整个结构才可以实现Drop
.Drop
if Drop::drop
does not move any of the fields for which there is a structural projection.#[repr(packed)]
(上一项的推论).#[repr(packed)]
(a corollary of the previous item).future::Map
example, this is the case of the future
field of the Map
struct.pin_utils::unsafe_unpinned!
宏用于定义此类投影(Pin<&mut Wrapper<Field>> -> &mut Field
).Pin<&mut Wrapper<Field>>
固定.Pin<&mut Wrapper<Field>>
.
Field
是否为Unpin
无关紧要.
允许
unsafe
将此类字段移出Pin<&mut Wrapper<Field>>
.例如,允许 Option::take()
.
unsafe
to move such fields out of a Pin<&mut Wrapper<Field>>
. For instance, Option::take()
is allowed.Drop::drop
移动此类字段,future::Map
example, this is the case of the f
field of the Map
struct.impl<Fut, F> Map<Fut, F> {
unsafe_pinned!(future: Fut); // pin projection -----+
unsafe_unpinned!(f: Option<F>); // not pinned --+ |
// | |
// ... | |
// | |
fn poll (mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
// | |
match self.as_mut().future().poll(cx) { // <----+ required here
Poll::Pending => Poll::Pending, // |
Poll::Ready(output) => { // |
let f = self.f().take() // <--------+ allows this