如何使用具有自引用结构的Pin结构?

时间:2018-04-16 14:46:20

标签: rust

我尝试使用新的Pin功能。阅读this blog post后,我开始编写一些代码:

#![feature(pin, arbitrary_self_types)]
use std::mem::Pin;

pub struct Foo {
    var: i32,
}

pub struct FooRef<'i> {
    ref_var: &'i i32,
    other: i32,
}

pub struct SimpleRef<'data> {
    foo: Box<Foo>,
    bar: Option<FooRef<'data>>,
}

impl<'data> SimpleRef<'data> {
    fn new() -> SimpleRef<'data> {
        SimpleRef {
            foo: Box::new({ Foo { var: 42 } }),
            bar: None,
        }
    }

    fn init(mut self: Pin<SimpleRef<'data>>) {
        let this: &mut SimpleRef = unsafe { Pin::get_mut(&mut self) };
        let a = FooRef {
            ref_var: &this.foo.var,
            other: 12,
        };
        this.bar = Some(a);
    }
}

fn main() {}

但是我收到了这个错误:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
  --> src/main.rs:27:45
   |
27 |         let this: &mut SimpleRef = unsafe { Pin::get_mut(&mut self) };
   |                                             ^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 26:5...
  --> src/main.rs:26:5
   |
26 | /     fn init(mut self: Pin<SimpleRef<'data>>) {
27 | |         let this: &mut SimpleRef = unsafe { Pin::get_mut(&mut self) };
28 | |         let a = FooRef {
29 | |             ref_var: &this.foo.var,
...  |
32 | |         this.bar = Some(a);
33 | |     }
   | |_____^
note: ...but the lifetime must also be valid for the lifetime 'data as defined on the impl at 18:1...
  --> src/main.rs:18:1
   |
18 | impl<'data> SimpleRef<'data> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: ...so that the expression is assignable:
           expected &mut std::mem::Pin<'_, SimpleRef<'_>>
              found &mut std::mem::Pin<'_, SimpleRef<'data>>

我的代码与博文中的代码之间的区别在于我使用带有生命周期参数的变量而不是原始指针。
是否可以使用寿命参数为Pin的变量?

1 个答案:

答案 0 :(得分:5)

  

是否可以使用寿命参数为Pin的变量?

可能。

  

我的代码和博客文章中的代码之间的区别在于我使用的是带有生命周期参数的变量,而不是原始指针。

这改变了一切:Rust语言不保证指针的有效性,但严格保证了引用的有效性。

让我们检查引用的生命周期问题,看看为什么本文专门使用原始指针(和unsafe代码)来解决这个问题。

Pin::get_mut的签名是:

pub unsafe fn get_mut<'b>(this: &'b mut Pin<'a, T>) -> &'b mut T

也就是说,只要对Pin的引用有效,引用才有效。

由于Pin通过值作为参数传递,因此它将在函数范围的末尾被删除。然而,您试图在此之后保留对它的引用。这是不安全

使用原始指针很好(未选中),因为尝试使用原始指针的人需要使用unsafe块,负责确保指针确实有效。