如何将Pin结构与自引用结构一起使用?

Séb*_*uis 5 rust

我正在尝试使用新Pin功能。阅读此博客文章之后,我开始编写一些代码:

#![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() {}
Run Code Online (Sandbox Code Playgroud)

但是我得到这个错误:

#![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() {}
Run Code Online (Sandbox Code Playgroud)

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

Mat*_* M. 7

是否可以将带有生命周期参数的变量与一起使用Pin

大概。

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

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

让我们研究一下引用的生命周期问题,并查看为什么本文专门使用原始指针(和unsafe代码)来克服该问题。


的签名Pin::get_mut是:

pub unsafe fn get_mut<'b>(this: &'b mut Pin<'a, T>) -> &'b mut T
Run Code Online (Sandbox Code Playgroud)

也就是说,该引用仅在对的引用有效时才Pin有效。

由于Pin通过值作为参数传递,因此将其放在函数作用域的末尾。但是,您尝试在此之后保留对它的引用。这是不安全的

使用原始指针是可以的(未经检查),因为任何尝试使用原始指针的人都将需要使用一个unsafe块,负责确保该指针确实有效。

  • @udoprog:我改写了有问题的部分。我不想“抨击” OP,只是要提请注意一个事实,那就是故意使用“不安全”(和原始指针),以及有关此问题的线索。 (2认同)