如何将 Pin 结构与自引用结构一起使用? [英] How to use the Pin struct with self-referential structures?

查看:59
本文介绍了如何将 Pin 结构与自引用结构一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用新的 Pin 功能.阅读这篇博文,我已经开始写一些代码了:

#![功能(pin,arbitrary_self_types)]使用 std::mem::Pin;酒吧结构 Foo {变量:i32,}pub struct FooRef<'i>{ref_var: &'i i32,其他:i32,}pub struct SimpleRef<'data>{foo: Box,bar: Option,}impl<'数据>SimpleRef<'data>{fn new() ->SimpleRef<'data>{简单引用 {foo: Box::new({ Foo { var: 42 } }),酒吧:无,}}fn init(mut self: Pin<SimpleRef<'data>>) {让这个: &mut SimpleRef = unsafe { Pin::get_mut(&mut self) };让 a = FooRef {ref_var: &this.foo.var,其他:12,};this.bar = Some(a);}}fn main() {}

但我收到此错误:

error[E0495]:由于需求冲突,无法为生命周期参数a"推断合适的生命周期-->src/main.rs:27:45|27 |让这个: &mut SimpleRef = unsafe { Pin::get_mut(&mut self) };|^^^^^^^^^^^^^|注意:首先,生命周期不能超过 26:5 方法主体上定义的匿名生命周期 #1 ...-->src/main.rs:26:5|26 |/fn init(mut self: Pin<SimpleRef<'data>>) {27 ||让这个: &mut SimpleRef = unsafe { Pin::get_mut(&mut self) };28 ||让 a = FooRef {29 ||ref_var: &this.foo.var,... |32 ||this.bar = Some(a);33 ||}||_____^注意:...但生命周期也必须对 18:1 impl 上定义的生命周期数据有效...-->src/main.rs:18:1|18 |impl<'数据>SimpleRef<'data>{|^^^^^^^^^^^^^^^^^^^^^^^^^^^^= 注意:...所以表达式是可赋值的:预期 &mut std::mem::Pin<'_, SimpleRef<'_>>found &mut std::mem::Pin<'_, SimpleRef<'data>>

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

是否可以通过 Pin 使用带有生命周期参数的变量?

可能.

<块引用>

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

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

让我们研究一下引用的生命周期问题,看看为什么这篇文章专门使用原始指针(和 unsafe 代码)来解决这个问题.

<小时>

Pin 的签名::get_mut 是:

<块引用>

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

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

由于 Pin 是按值作为参数传递的,因此它被丢弃在函数作用域的末尾.然而,您试图在该点之后保留对它的引用.这是不安全.

使用原始指针很好(未检查),因为任何尝试使用原始指针的人都需要使用 unsafe 块,负责确保指针确实有效.

I'm trying to use the new Pin feature. After reading this blog post, I've started to write some code:

#![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() {}

But I get this error:

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>>

The difference between my code and the code in the blog post is that I'm using a variable with a lifetime parameter, instead of a raw pointer.
Is it possible to use variables with lifetime parameters with Pin?

解决方案

Is it possible to use variables with lifetime parameters with Pin?

Probably.

The difference between my code and the code in the blog post is that I'm using a variable with a lifetime parameter, instead of a raw pointer.

This changes everything: the Rust language makes no guarantee on the validity of pointers, but makes strict guarantees on the validity of references.

Let's examine the lifetime issue of references and see why the article specifically used raw pointers (and unsafe code) to overcome the issue.


The signature of Pin::get_mut is:

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

That is, the reference is only valid as long as the reference to Pin is valid.

Since Pin is passed by value as argument, it is dropped at the end of the function scope. Yet, you attempt to retain a reference to it beyond that point. This is unsafe.

Using raw pointers is fine (unchecked), because whoever attempts to use the raw pointer will need to use an unsafe block, taking responsibility for ensuring that the pointer is indeed valid.

这篇关于如何将 Pin 结构与自引用结构一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆