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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
use crate::async_iter::AsyncIterator;
use crate::cell::UnsafeCell;
use crate::fmt;
use crate::future::Future;
use crate::ops::{Deref, DerefMut};
use crate::pin::Pin;
use crate::ptr::{NonNull, Unique};
use crate::task::{Context, Poll};

/// 表示 Rust 中 "panic safe" 类型的标记 trait。
///
/// 默认情况下,此 trait 对许多类型都实现,并且在推断实现时类似于 [`Send`] 和 [`Sync`] traits。
/// 这个 trait 的目的是编码哪些类型可以安全地越过 [`catch_unwind`] 边界,而不必担心 unwind 安全。
///
/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html
///
/// ## 什么是 unwind 安全性?
///
/// 在 Rust 中,如果一个函数可以 0panics 或调用一个传递 panics 的函数,则可以提前 "return"。
/// 这种控制流并非总是可以预期的,并且有可能通过结合以下两个关键组件而导致细微的错误:
///
/// 1. 当线程 panics 时,数据结构体处于暂时无效状态。
/// 2. 然后,随后观察到该损坏的不变量。
///
/// 通常在 Rust 中,很难执行步骤 (2),因为捕获 panic 涉及生成线程 (这反过来使得以后很难看到损坏的不,变体) 或使用此模块中的 `catch_unwind` 函数。
///
/// 此外,即使看到一个不变量,它在 Rust 中通常也不是问题,因为没有未初始化的值 (如 C 或 C++ )。
///
/// 然而,在 Rust 中,**logical** 不变量有可能会被破坏,这最终会导致行为 Bug。
/// Rust 中 unwind 安全性的另一个关键方面是,在没有 `unsafe` 代码的情况下,panic 不会导致内存不安全。
///
/// 那是 unwind 安全性的旋风之旅,但是有关 unwind 安全性及其如何应用于 Rust 的更多信息,请参见 [相关的 RFC][rfc]。
///
/// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
///
/// ## 什么是 `UnwindSafe`?
///
/// 现在我们已经了解了 Rust 中的 unwind 安全性,了解此 trait 所代表的意义也很重要。
/// 如上所述,见证不变量被破坏的一种方法是通过这个模块中的 `catch_explode` 函数,因为它允许捕获一个 panic,然后重新使用闭包的环境。
///
/// 简而言之,如果类型 `T` 无法通过使用 `catch_unwind` (捕获 panic) 来轻松地见证损坏的不变量,则可以实现 `UnwindSafe`。
/// 这个 trait 是自动 trait,所以它是针对多种类型自动实现的,并且它也是由结构体组成的 (例如,如果结构体的所有组件都是 unwind 安全的,则该结构体是 unwind 安全的)。
///
/// 但是请注意,这不是不安全的 trait,因此该 trait 没有提供简洁的契约。
/// 相反,它旨在作为 "speed bump" 的一部分,以警告 `catch_unwind` 用户,可能会目击到损坏的不变量,并且可能需要解决这些不变量。
///
/// ## 谁实现 `UnwindSafe`?
///
/// `&mut T` 和 `&RefCell<T>` 之类的类型是 unwind 不安全的示例。通常的想法是,默认情况下,可以在 `catch_unwind` 之间共享的任何可变状态都不是 unwind 安全的。
/// 这是因为在 `catch_unwind` 之外很容易看到损坏的不变量,因为数据可以像往常一样简单地访问。
///
/// 但是,像 `&Mutex<T>` 这样的类型是 unwind 安全的,因为它们默认实现中毒。他们仍然可以目击损坏的不变量,但是他们已经提供了自己的 "speed bumps" 来做到这一点。
///
/// ## 什么时候应使用 `UnwindSafe`?
///
/// 并非意味着大多数类型或函数都不必担心此 trait。
/// 它仅用作 `catch_unwind` 函数的绑定,如上所述,缺少 `unsafe` 意味着它主要是建议。
/// [`AssertUnwindSafe`] 包装器结构体可用于强制将 trait 应用于传递给 `catch_unwind` 的任何封闭变量。
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
#[stable(feature = "catch_unwind", since = "1.9.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "unwind_safe_trait")]
#[rustc_on_unimplemented(
    message = "the type `{Self}` may not be safely transferred across an unwind boundary",
    label = "`{Self}` may not be safely transferred across an unwind boundary"
)]
pub auto trait UnwindSafe {}

/// 一种标记 trait,表示共享引用被认为是 unwind 安全的类型。
///
/// 即,该 trait 并非由 [`UnsafeCell`] 实现,[`UnsafeCell`] 是所有内部可变性的根。
///
/// 这是 "辅助标记 trait",用于为 [`UnwindSafe`] trait 提供 impl 块,有关更多信息,请参见该文档。
///
///
///
#[stable(feature = "catch_unwind", since = "1.9.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "ref_unwind_safe_trait")]
#[rustc_on_unimplemented(
    message = "the type `{Self}` may contain interior mutability and a reference may not be safely \
               transferrable across a catch_unwind boundary",
    label = "`{Self}` may contain interior mutability and a reference may not be safely \
             transferrable across a catch_unwind boundary"
)]
pub auto trait RefUnwindSafe {}

/// 一个简单的包装器,可以断言它是 unwind 安全的。
///
/// 使用 [`catch_unwind`] 时,可能某些封闭变量不是 unwind 安全的。例如,如果捕获了 `&mut T`,编译器将生成一条警告,指出它不是 unwind 安全的。
/// 然而,如果特别考虑到展开安全,这实际上可能不是由于 [`catch_unwind`] 的特定用途而造成的问题。
/// 此包装结构体对于快速且轻便的注解很有用,因为变量确实是 unwind 安全的。
///
/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html
///
/// # Examples
///
/// 使用 `AssertUnwindSafe` 的一种方法是断言整个闭包本身是 unwind 安全的,绕过所有变量的所有检查:
///
/// ```
/// use std::panic::{self, AssertUnwindSafe};
///
/// let mut variable = 4;
///
/// // 由于闭包捕获 `&mut variable` (默认情况下不认为 unwind 安全),因此不会编译该代码。
/////
///
/// // panic::catch_unwind(|| { variable += 3; });
/////
/////
///
/// // 但是,由于 `AssertUnwindSafe` 包装器,它将进行编译
/// let result = panic::catch_unwind(AssertUnwindSafe(|| {
///     variable += 3;
/// }));
/// // ...
/// ```
///
/// 包装整个闭包就等于断言所有捕获的变量都是 unwind 安全的。不利之处在于,如果在 future 中添加了新的捕获,它们也将被视为 unwind 安全。
/// 因此,您可能希望只包装单个捕获,如下所示。
/// 这是更多的注解,但是它可以确保如果添加的 unwind 不安全的新捕获,您将在那时遇到编译错误,这将使您考虑该新捕获是否实际上代表错误。
///
///
/// ```
/// use std::panic::{self, AssertUnwindSafe};
///
/// let mut variable = 4;
/// let other_capture = 3;
///
/// let result = {
///     let mut wrapper = AssertUnwindSafe(&mut variable);
///     panic::catch_unwind(move || {
///         **wrapper += other_capture;
///     })
/// };
/// // ...
/// ```
///
///
///
///
///
///
///
///
///
#[stable(feature = "catch_unwind", since = "1.9.0")]
pub struct AssertUnwindSafe<T>(#[stable(feature = "catch_unwind", since = "1.9.0")] pub T);

// `UnwindSafe` trait 的实现:
//
// * 默认情况下,所有内容都是 unwind 安全的
// * 指针 T 包含某种形式的可变性不是 unwind 安全的
// * 唯一的拥有指针,可以提升实现
// * 像 Mutex/RwLock 这样被明确中毒的类型是 unwind 安全的
// * 我们的自定义 AssertUnwindSafe 包装器确实是 unwind 安全的

#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: ?Sized> !UnwindSafe for &mut T {}
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for &T {}
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *const T {}
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *mut T {}
#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: UnwindSafe + ?Sized> UnwindSafe for Unique<T> {}
#[stable(feature = "nonnull", since = "1.25.0")]
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for NonNull<T> {}
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T> UnwindSafe for AssertUnwindSafe<T> {}

// `RefUnwindSafe` 标记 trait 的非常简单的实现,基本上只是说 `UnsafeCell` 是唯一不实现它的东西 (然后将其可传递地应用于其他所有东西)。
//
//
//
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: ?Sized> !RefUnwindSafe for UnsafeCell<T> {}
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T> RefUnwindSafe for AssertUnwindSafe<T> {}

#[cfg(target_has_atomic_load_store = "ptr")]
#[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
impl RefUnwindSafe for crate::sync::atomic::AtomicIsize {}
#[cfg(target_has_atomic_load_store = "8")]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl RefUnwindSafe for crate::sync::atomic::AtomicI8 {}
#[cfg(target_has_atomic_load_store = "16")]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl RefUnwindSafe for crate::sync::atomic::AtomicI16 {}
#[cfg(target_has_atomic_load_store = "32")]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl RefUnwindSafe for crate::sync::atomic::AtomicI32 {}
#[cfg(target_has_atomic_load_store = "64")]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl RefUnwindSafe for crate::sync::atomic::AtomicI64 {}
#[cfg(target_has_atomic_load_store = "128")]
#[unstable(feature = "integer_atomics", issue = "99069")]
impl RefUnwindSafe for crate::sync::atomic::AtomicI128 {}

#[cfg(target_has_atomic_load_store = "ptr")]
#[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
impl RefUnwindSafe for crate::sync::atomic::AtomicUsize {}
#[cfg(target_has_atomic_load_store = "8")]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl RefUnwindSafe for crate::sync::atomic::AtomicU8 {}
#[cfg(target_has_atomic_load_store = "16")]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl RefUnwindSafe for crate::sync::atomic::AtomicU16 {}
#[cfg(target_has_atomic_load_store = "32")]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl RefUnwindSafe for crate::sync::atomic::AtomicU32 {}
#[cfg(target_has_atomic_load_store = "64")]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl RefUnwindSafe for crate::sync::atomic::AtomicU64 {}
#[cfg(target_has_atomic_load_store = "128")]
#[unstable(feature = "integer_atomics", issue = "99069")]
impl RefUnwindSafe for crate::sync::atomic::AtomicU128 {}

#[cfg(target_has_atomic_load_store = "8")]
#[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
impl RefUnwindSafe for crate::sync::atomic::AtomicBool {}

#[cfg(target_has_atomic_load_store = "ptr")]
#[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
impl<T> RefUnwindSafe for crate::sync::atomic::AtomicPtr<T> {}

#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T> Deref for AssertUnwindSafe<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T> DerefMut for AssertUnwindSafe<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<R, F: FnOnce() -> R> FnOnce<()> for AssertUnwindSafe<F> {
    type Output = R;

    extern "rust-call" fn call_once(self, _args: ()) -> R {
        (self.0)()
    }
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_tuple("AssertUnwindSafe").field(&self.0).finish()
    }
}

#[stable(feature = "assertunwindsafe_default", since = "1.62.0")]
impl<T: Default> Default for AssertUnwindSafe<T> {
    fn default() -> Self {
        Self(Default::default())
    }
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl<F: Future> Future for AssertUnwindSafe<F> {
    type Output = F::Output;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        // SAFETY: pin projection。 AssertUnwindSafe 遵循结构固定。
        let pinned_field = unsafe { Pin::map_unchecked_mut(self, |x| &mut x.0) };
        F::poll(pinned_field, cx)
    }
}

#[unstable(feature = "async_iterator", issue = "79024")]
impl<S: AsyncIterator> AsyncIterator for AssertUnwindSafe<S> {
    type Item = S::Item;

    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<S::Item>> {
        // SAFETY: pin projection。 AssertUnwindSafe 遵循结构固定。
        unsafe { self.map_unchecked_mut(|x| &mut x.0) }.poll_next(cx)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.0.size_hint()
    }
}