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
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
//! 标准库中的 Panic 支持。

#![stable(feature = "std_panic", since = "1.9.0")]

use crate::any::Any;
use crate::cell::UnsafeCell;
use crate::collections;
use crate::fmt;
use crate::future::Future;
use crate::ops::{Deref, DerefMut};
use crate::panicking;
use crate::pin::Pin;
use crate::ptr::{NonNull, Unique};
use crate::rc::Rc;
use crate::stream::Stream;
use crate::sync::atomic;
use crate::sync::{Arc, Mutex, RwLock};
use crate::task::{Context, Poll};
use crate::thread::Result;

#[doc(hidden)]
#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
#[allow_internal_unstable(libstd_sys_internals)]
#[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_2015_macro")]
#[rustc_macro_transparency = "semitransparent"]
pub macro panic_2015 {
    () => ({
        $crate::rt::begin_panic("explicit panic")
    }),
    ($msg:expr $(,)?) => ({
        $crate::rt::begin_panic($msg)
    }),
    ($fmt:expr, $($arg:tt)+) => ({
        $crate::rt::begin_panic_fmt(&$crate::format_args!($fmt, $($arg)+))
    }),
}

#[doc(hidden)]
#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
pub use core::panic::panic_2021;

#[stable(feature = "panic_hooks", since = "1.10.0")]
pub use crate::panicking::{set_hook, take_hook};

#[stable(feature = "panic_hooks", since = "1.10.0")]
pub use core::panic::{Location, PanicInfo};

/// Panic 当前线程,给定消息为 panic 有效负载。
///
/// 该消息可以是任何 (`Any + Send`) 类型,而不仅仅是字符串。
///
/// 该消息包装在 `Box<'static + Any + Send>` 中,以后可以使用 [`PanicInfo::payload`] 进行访问。
///
///
/// 有关恐慌的更多信息,请参见 [`panic!`] 宏。
#[stable(feature = "panic_any", since = "1.51.0")]
#[inline]
#[track_caller]
pub fn panic_any<M: 'static + Any + Send>(msg: M) -> ! {
    crate::panicking::begin_panic(msg);
}

/// 表示 Rust 中 "panic safe" 类型的标记 trait。
///
/// 默认情况下,此 trait 对许多类型都实现,并且在推断实现时类似于 [`Send`] 和 [`Sync`] traits。
/// trait 的目的是对可以跨越 [`catch_unwind`] 边界安全的类型进行编码,而不必担心 unwind 安全。
///
/// ## 什么是 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 的更多信息,请参见 [associated RFC][rfc]。
///
/// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
///
/// ## 什么是 `UnwindSafe`?
///
/// 现在我们已经了解了 Rust 中的 unwind 安全性,了解此 trait 所代表的意义也很重要。
/// 如上所述,见证不可变变量不变的一种方法是通过此模块中的 `catch_unwind` 函数,因为它允许捕获 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 表示将 X 表示 unwind 安全的共享引用的类型。
///
/// 即,该 trait 并非由 [`UnsafeCell`] 实现,[`UnsafeCell`] 是所有内部可变性的根。
///
/// 这是 "helper marker 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 安全的。
/// 但是,如果特别考虑了 unwind 的安全性,则由于 [`catch_unwind`] 的特定用法,实际上可能不是问题。
/// 此包装结构体对于快速且轻便的注解很有用,因为变量确实是 unwind 安全的。
///
/// # 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: ?Sized> UnwindSafe for Mutex<T> {}
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: ?Sized> UnwindSafe for RwLock<T> {}
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T> UnwindSafe for AssertUnwindSafe<T> {}

// 未通过 b/c 上方的共享 impl 覆盖,内部内容使用 Cell/AtomicUsize,但此处的用法是 unwind 安全的,因此我们可以将 impl 提升至 Arc/Rc 本身
//
//
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Rc<T> {}
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Arc<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> {}

#[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")]
impl<T: ?Sized> RefUnwindSafe for Mutex<T> {}
#[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")]
impl<T: ?Sized> RefUnwindSafe for RwLock<T> {}

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

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

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

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

// https://github.com/rust-lang/rust/issues/62301
#[stable(feature = "hashbrown", since = "1.36.0")]
impl<K, V, S> UnwindSafe for collections::HashMap<K, V, S>
where
    K: UnwindSafe,
    V: UnwindSafe,
    S: UnwindSafe,
{
}

#[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 = "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> {
        let pinned_field = unsafe { Pin::map_unchecked_mut(self, |x| &mut x.0) };
        F::poll(pinned_field, cx)
    }
}

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

    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<S::Item>> {
        unsafe { self.map_unchecked_mut(|x| &mut x.0) }.poll_next(cx)
    }

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

/// 调用一个闭包,如果发生,则捕获展开 panic 的原因。
///
/// 如果闭包不是 panic,则此函数将返回 `Ok`,并返回闭包的结果; 如果闭包 panics,则此函数将返回 `Err(cause)`。
/// 返回的 `cause` 是最初调用 panic 的 object。
///
/// unwind 当前从 Rust 代码转换为外来代码是未定义的行为,因此当从另一种语言 (通常为 C) 调用 Rust 时,此函数特别有用。
/// 这可以运行任意的 Rust 代码,捕获 panic 并允许对错误进行适当的处理。
///
/// 不建议将此函数用于一般的 try/catch 机制。
/// [`Result`] 类型更适合用于经常失败的函数。
/// 此外,不能保证此函数可以捕获所有 panics,请参见下面的 "Notes" 部分。
///
/// 提供的闭包必须遵守 [`UnwindSafe`] trait,以确保所有捕获的变量都可以安全越过此边界。
/// 此绑定的目的是在类型系统中对 [异常安全][rfc] 的概念进行编码。
/// 此函数的大多数用法都不必担心此绑定,因为没有 `unsafe` 代码的程序自然是 unwind 安全的。
/// 如果出现问题,可以使用 [`AssertUnwindSafe`] 包装器结构体快速断言此处的使用确实是 unwind 安全的。
///
/// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
///
/// # Notes
///
/// 请注意,此函数 **可能无法捕获 Rust 中的所有 panics**。Rust 中的 panic 并不总是通过展开来实现,但是也可以通过终止进程来实现。
///
/// 该函数 *仅* 捕获展开 panics,而不是终止进程的 panics。
///
/// 另请注意,使用外部异常 (例如,展开为 Rust 代码)
/// 从 C++ 代码引发的异常) 是未定义的行为。
///
/// # Examples
///
/// ```
/// use std::panic;
///
/// let result = panic::catch_unwind(|| {
///     println!("hello!");
/// });
/// assert!(result.is_ok());
///
/// let result = panic::catch_unwind(|| {
///     panic!("oh no!");
/// });
/// assert!(result.is_err());
/// ```
///
///
///
///
///
///
///
///
#[stable(feature = "catch_unwind", since = "1.9.0")]
pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
    unsafe { panicking::r#try(f) }
}

/// 触发 panic 而不调用 panic hook。
///
/// 它被设计为与 [`catch_unwind`] 结合使用,例如,跨 C 代码层携带 panic。
///
/// # Notes
///
/// 请注意,Rust 中的 panics 并不总是通过展开来实现,但是可以通过中止进程来实现。
/// 如果以这种方式实现 panics 时调用了此函数,则此函数将终止进程,而不触发 unwind。
///
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// let result = panic::catch_unwind(|| {
///     panic!("oh no!");
/// });
///
/// if let Err(err) = result {
///     panic::resume_unwind(err);
/// }
/// ```
///
///
#[stable(feature = "resume_unwind", since = "1.9.0")]
pub fn resume_unwind(payload: Box<dyn Any + Send>) -> ! {
    panicking::rust_panic_without_hook(payload)
}

/// 使所有 future panics 直接终止而不运行 panic hook 或展开。
///
/// 没有办法撤销这个; 效果持续到进程退出或执行 (或等效)。
///
/// # fork 后使用
///
/// 这个函数在 `libc::fork` 之后调用特别有用。在 `fork` 之后,在多线程程序中 (在许多平台上) 调用分配器是不安全的。
/// `fork` 之后的 unwind 到 unwind 通常也是非常不可取的,因为这会导致 unwind 传播到只希望在父级中运行的代码。
///
///
/// `panic::always_abort()` 有助于避免这两种情况。
/// 它直接避免了任何进一步的展开,如果存在 panic,则无需分配即可终止终止,前提是 panic 的参数可以在不分配的情况下进行格式化。
///
/// Examples
///
/// ```no_run
/// #![feature(panic_always_abort)]
/// use std::panic;
///
/// panic::always_abort();
///
/// let _ = panic::catch_unwind(|| {
///     panic!("inside the catch");
/// });
///
/// // 由于 panic,我们已经中止了。
/// unreachable!();
/// ```
///
///
///
#[unstable(feature = "panic_always_abort", issue = "84438")]
pub fn always_abort() {
    crate::panicking::panic_count::set_always_abort();
}

#[cfg(test)]
mod tests;