Rust Pin

以下内容均摘自async-book

自引用类型问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#[derive(Debug)]
struct Test {
a: String,
b: *const String,
}

impl Test {
fn new(txt: &str) -> Self {
Test {
a: String::from(txt),
b: std::ptr::null(),
}
}

fn init(&mut self) {
let self_ref: *const String = &self.a;
self.b = self_ref;
}

fn a(&self) -> &str {
&self.a
}

fn b(&self) -> &String {
assert!(!self.b.is_null(), "Test::b called without Test::init being called first");
unsafe { &*(self.b) }
}
}

fn main() {
let mut test1 = Test::new("test1");
test1.init();
let mut test2 = Test::new("test2");
test2.init();

println!("a: {}, b: {}", test1.a(), test1.b());
std::mem::swap(&mut test1, &mut test2);
println!("a: {}, b: {}", test2.a(), test2.b());

}

以上代码会输出:

1
2
a: test1, b: test1
a: test1, b: test2

交换前后所发生的事情:

知乎

知乎
自引用结构体的问题在于移动可能会导致引用成员变成野指针。那么解决办法也很简单,不让自引用结构体内存发生移动。这也就是Pin,中文意思是钉住,即把内存钉住,不让其发生移动。