如何使用具有自引用结构的 Pin 结构?
How to use the Pin struct with self-referential structures?
我正在尝试使用新的 Pin
feature. After reading 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>>
我的代码和博客中代码的区别 post 是我使用的是带有生命周期参数的变量,而不是原始指针。
是否可以使用带有生命周期参数的变量 Pin
?
Is it possible to use variables with lifetime parameters with Pin
?
可能。
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.
这改变了一切:Rust 语言不保证指针的有效性,但严格保证引用的有效性。
让我们检查一下引用的生命周期问题,看看为什么这篇文章专门使用原始指针(和 unsafe
代码)来解决这个问题。
Pin::get_mut
的签名是:
pub unsafe fn get_mut<'b>(this: &'b mut Pin<'a, T>) -> &'b mut T
也就是说,只要对Pin
的引用有效,引用才有效。
因为 Pin
是通过值作为参数传递的,所以它在函数范围的末尾被删除。然而,您试图在该点之后保留对它的引用。这是不安全。
使用裸指针是可以的(未选中),因为任何试图使用裸指针的人都需要使用 unsafe
块,负责确保指针确实有效。
我正在尝试使用新的 Pin
feature. After reading 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>>
我的代码和博客中代码的区别 post 是我使用的是带有生命周期参数的变量,而不是原始指针。
是否可以使用带有生命周期参数的变量 Pin
?
Is it possible to use variables with lifetime parameters with
Pin
?
可能。
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.
这改变了一切:Rust 语言不保证指针的有效性,但严格保证引用的有效性。
让我们检查一下引用的生命周期问题,看看为什么这篇文章专门使用原始指针(和 unsafe
代码)来解决这个问题。
Pin::get_mut
的签名是:
pub unsafe fn get_mut<'b>(this: &'b mut Pin<'a, T>) -> &'b mut T
也就是说,只要对Pin
的引用有效,引用才有效。
因为 Pin
是通过值作为参数传递的,所以它在函数范围的末尾被删除。然而,您试图在该点之后保留对它的引用。这是不安全。
使用裸指针是可以的(未选中),因为任何试图使用裸指针的人都需要使用 unsafe
块,负责确保指针确实有效。