]>
Commit | Line | Data |
---|---|---|
ff7c6d11 | 1 | //! Panic support in the standard library. |
9cc50fc6 | 2 | |
54a0048b | 3 | #![stable(feature = "std_panic", since = "1.9.0")] |
9cc50fc6 | 4 | |
532ac7d7 XL |
5 | use crate::any::Any; |
6 | use crate::cell::UnsafeCell; | |
48663c56 | 7 | use crate::collections; |
532ac7d7 XL |
8 | use crate::fmt; |
9 | use crate::future::Future; | |
532ac7d7 XL |
10 | use crate::ops::{Deref, DerefMut}; |
11 | use crate::panicking; | |
60c5eb7d XL |
12 | use crate::pin::Pin; |
13 | use crate::ptr::{NonNull, Unique}; | |
532ac7d7 | 14 | use crate::rc::Rc; |
5869c6ff | 15 | use crate::stream::Stream; |
e74abb32 | 16 | use crate::sync::atomic; |
60c5eb7d | 17 | use crate::sync::{Arc, Mutex, RwLock}; |
532ac7d7 XL |
18 | use crate::task::{Context, Poll}; |
19 | use crate::thread::Result; | |
9cc50fc6 | 20 | |
5869c6ff XL |
21 | #[doc(hidden)] |
22 | #[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")] | |
23 | #[allow_internal_unstable(libstd_sys_internals)] | |
24 | #[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_2015_macro")] | |
25 | #[rustc_macro_transparency = "semitransparent"] | |
26 | pub macro panic_2015 { | |
27 | () => ({ | |
28 | $crate::rt::begin_panic("explicit panic") | |
29 | }), | |
30 | ($msg:expr $(,)?) => ({ | |
31 | $crate::rt::begin_panic($msg) | |
32 | }), | |
33 | ($fmt:expr, $($arg:tt)+) => ({ | |
34 | $crate::rt::begin_panic_fmt(&$crate::format_args!($fmt, $($arg)+)) | |
35 | }), | |
36 | } | |
37 | ||
38 | #[doc(hidden)] | |
39 | #[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")] | |
40 | pub use core::panic::panic_2021; | |
41 | ||
a7813a04 | 42 | #[stable(feature = "panic_hooks", since = "1.10.0")] |
60c5eb7d | 43 | pub use crate::panicking::{set_hook, take_hook}; |
0531ce1d XL |
44 | |
45 | #[stable(feature = "panic_hooks", since = "1.10.0")] | |
60c5eb7d | 46 | pub use core::panic::{Location, PanicInfo}; |
54a0048b | 47 | |
29967ef6 XL |
48 | /// Panic the current thread with the given message as the panic payload. |
49 | /// | |
50 | /// The message can be of any (`Any + Send`) type, not just strings. | |
51 | /// | |
52 | /// The message is wrapped in a `Box<'static + Any + Send>`, which can be | |
53 | /// accessed later using [`PanicInfo::payload`]. | |
54 | /// | |
55 | /// See the [`panic!`] macro for more information about panicking. | |
5869c6ff | 56 | #[stable(feature = "panic_any", since = "1.51.0")] |
29967ef6 | 57 | #[inline] |
5869c6ff | 58 | pub fn panic_any<M: 'static + Any + Send>(msg: M) -> ! { |
29967ef6 XL |
59 | crate::panicking::begin_panic(msg); |
60 | } | |
61 | ||
9cc50fc6 SL |
62 | /// A marker trait which represents "panic safe" types in Rust. |
63 | /// | |
64 | /// This trait is implemented by default for many types and behaves similarly in | |
83c7162d XL |
65 | /// terms of inference of implementation to the [`Send`] and [`Sync`] traits. The |
66 | /// purpose of this trait is to encode what types are safe to cross a [`catch_unwind`] | |
3157f602 | 67 | /// boundary with no fear of unwind safety. |
9cc50fc6 | 68 | /// |
3157f602 | 69 | /// ## What is unwind safety? |
9cc50fc6 SL |
70 | /// |
71 | /// In Rust a function can "return" early if it either panics or calls a | |
72 | /// function which transitively panics. This sort of control flow is not always | |
73 | /// anticipated, and has the possibility of causing subtle bugs through a | |
3b2f2976 | 74 | /// combination of two critical components: |
9cc50fc6 SL |
75 | /// |
76 | /// 1. A data structure is in a temporarily invalid state when the thread | |
77 | /// panics. | |
78 | /// 2. This broken invariant is then later observed. | |
79 | /// | |
80 | /// Typically in Rust, it is difficult to perform step (2) because catching a | |
81 | /// panic involves either spawning a thread (which in turns makes it difficult | |
3157f602 | 82 | /// to later witness broken invariants) or using the `catch_unwind` function in this |
9cc50fc6 | 83 | /// module. Additionally, even if an invariant is witnessed, it typically isn't a |
3157f602 | 84 | /// problem in Rust because there are no uninitialized values (like in C or C++). |
9cc50fc6 SL |
85 | /// |
86 | /// It is possible, however, for **logical** invariants to be broken in Rust, | |
3157f602 | 87 | /// which can end up causing behavioral bugs. Another key aspect of unwind safety |
9cc50fc6 SL |
88 | /// in Rust is that, in the absence of `unsafe` code, a panic cannot lead to |
89 | /// memory unsafety. | |
90 | /// | |
3157f602 XL |
91 | /// That was a bit of a whirlwind tour of unwind safety, but for more information |
92 | /// about unwind safety and how it applies to Rust, see an [associated RFC][rfc]. | |
9cc50fc6 SL |
93 | /// |
94 | /// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md | |
95 | /// | |
a7813a04 | 96 | /// ## What is `UnwindSafe`? |
9cc50fc6 | 97 | /// |
3157f602 | 98 | /// Now that we've got an idea of what unwind safety is in Rust, it's also |
9cc50fc6 | 99 | /// important to understand what this trait represents. As mentioned above, one |
3157f602 | 100 | /// way to witness broken invariants is through the `catch_unwind` function in this |
9cc50fc6 SL |
101 | /// module as it allows catching a panic and then re-using the environment of |
102 | /// the closure. | |
103 | /// | |
a7813a04 | 104 | /// Simply put, a type `T` implements `UnwindSafe` if it cannot easily allow |
3157f602 | 105 | /// witnessing a broken invariant through the use of `catch_unwind` (catching a |
0bf4aa26 | 106 | /// panic). This trait is an auto trait, so it is automatically implemented for |
0731742a | 107 | /// many types, and it is also structurally composed (e.g., a struct is unwind |
3157f602 | 108 | /// safe if all of its components are unwind safe). |
9cc50fc6 SL |
109 | /// |
110 | /// Note, however, that this is not an unsafe trait, so there is not a succinct | |
111 | /// contract that this trait is providing. Instead it is intended as more of a | |
3157f602 | 112 | /// "speed bump" to alert users of `catch_unwind` that broken invariants may be |
9cc50fc6 SL |
113 | /// witnessed and may need to be accounted for. |
114 | /// | |
54a0048b | 115 | /// ## Who implements `UnwindSafe`? |
9cc50fc6 SL |
116 | /// |
117 | /// Types such as `&mut T` and `&RefCell<T>` are examples which are **not** | |
3157f602 XL |
118 | /// unwind safe. The general idea is that any mutable state which can be shared |
119 | /// across `catch_unwind` is not unwind safe by default. This is because it is very | |
120 | /// easy to witness a broken invariant outside of `catch_unwind` as the data is | |
7453a54e | 121 | /// simply accessed as usual. |
9cc50fc6 | 122 | /// |
3157f602 | 123 | /// Types like `&Mutex<T>`, however, are unwind safe because they implement |
9cc50fc6 SL |
124 | /// poisoning by default. They still allow witnessing a broken invariant, but |
125 | /// they already provide their own "speed bumps" to do so. | |
126 | /// | |
54a0048b | 127 | /// ## When should `UnwindSafe` be used? |
9cc50fc6 | 128 | /// |
83c7162d XL |
129 | /// It is not intended that most types or functions need to worry about this trait. |
130 | /// It is only used as a bound on the `catch_unwind` function and as mentioned | |
131 | /// above, the lack of `unsafe` means it is mostly an advisory. The | |
132 | /// [`AssertUnwindSafe`] wrapper struct can be used to force this trait to be | |
133 | /// implemented for any closed over variables passed to `catch_unwind`. | |
54a0048b | 134 | #[stable(feature = "catch_unwind", since = "1.9.0")] |
8faf50e0 | 135 | #[rustc_on_unimplemented( |
60c5eb7d XL |
136 | message = "the type `{Self}` may not be safely transferred across an unwind boundary", |
137 | label = "`{Self}` may not be safely transferred across an unwind boundary" | |
8faf50e0 | 138 | )] |
2c00a5a8 | 139 | pub auto trait UnwindSafe {} |
54a0048b | 140 | |
9cc50fc6 | 141 | /// A marker trait representing types where a shared reference is considered |
3157f602 | 142 | /// unwind safe. |
9cc50fc6 | 143 | /// |
83c7162d | 144 | /// This trait is namely not implemented by [`UnsafeCell`], the root of all |
9cc50fc6 SL |
145 | /// interior mutability. |
146 | /// | |
147 | /// This is a "helper marker trait" used to provide impl blocks for the | |
83c7162d | 148 | /// [`UnwindSafe`] trait, for more information see that documentation. |
54a0048b | 149 | #[stable(feature = "catch_unwind", since = "1.9.0")] |
8faf50e0 | 150 | #[rustc_on_unimplemented( |
60c5eb7d XL |
151 | message = "the type `{Self}` may contain interior mutability and a reference may not be safely \ |
152 | transferrable across a catch_unwind boundary", | |
153 | label = "`{Self}` may contain interior mutability and a reference may not be safely \ | |
154 | transferrable across a catch_unwind boundary" | |
8faf50e0 | 155 | )] |
2c00a5a8 | 156 | pub auto trait RefUnwindSafe {} |
9cc50fc6 | 157 | |
3157f602 | 158 | /// A simple wrapper around a type to assert that it is unwind safe. |
9cc50fc6 | 159 | /// |
83c7162d | 160 | /// When using [`catch_unwind`] it may be the case that some of the closed over |
3157f602 XL |
161 | /// variables are not unwind safe. For example if `&mut T` is captured the |
162 | /// compiler will generate a warning indicating that it is not unwind safe. It | |
9cc50fc6 | 163 | /// may not be the case, however, that this is actually a problem due to the |
83c7162d | 164 | /// specific usage of [`catch_unwind`] if unwind safety is specifically taken into |
9cc50fc6 | 165 | /// account. This wrapper struct is useful for a quick and lightweight |
3157f602 | 166 | /// annotation that a variable is indeed unwind safe. |
9cc50fc6 SL |
167 | /// |
168 | /// # Examples | |
169 | /// | |
54a0048b | 170 | /// One way to use `AssertUnwindSafe` is to assert that the entire closure |
3157f602 | 171 | /// itself is unwind safe, bypassing all checks for all variables: |
9cc50fc6 | 172 | /// |
54a0048b SL |
173 | /// ``` |
174 | /// use std::panic::{self, AssertUnwindSafe}; | |
9cc50fc6 SL |
175 | /// |
176 | /// let mut variable = 4; | |
177 | /// | |
178 | /// // This code will not compile because the closure captures `&mut variable` | |
3157f602 | 179 | /// // which is not considered unwind safe by default. |
9cc50fc6 | 180 | /// |
54a0048b | 181 | /// // panic::catch_unwind(|| { |
9cc50fc6 SL |
182 | /// // variable += 3; |
183 | /// // }); | |
184 | /// | |
54a0048b SL |
185 | /// // This, however, will compile due to the `AssertUnwindSafe` wrapper |
186 | /// let result = panic::catch_unwind(AssertUnwindSafe(|| { | |
187 | /// variable += 3; | |
188 | /// })); | |
189 | /// // ... | |
190 | /// ``` | |
191 | /// | |
192 | /// Wrapping the entire closure amounts to a blanket assertion that all captured | |
193 | /// variables are unwind safe. This has the downside that if new captures are | |
194 | /// added in the future, they will also be considered unwind safe. Therefore, | |
195 | /// you may prefer to just wrap individual captures, as shown below. This is | |
196 | /// more annotation, but it ensures that if a new capture is added which is not | |
197 | /// unwind safe, you will get a compilation error at that time, which will | |
198 | /// allow you to consider whether that new capture in fact represent a bug or | |
199 | /// not. | |
200 | /// | |
201 | /// ``` | |
202 | /// use std::panic::{self, AssertUnwindSafe}; | |
203 | /// | |
204 | /// let mut variable = 4; | |
205 | /// let other_capture = 3; | |
206 | /// | |
9cc50fc6 | 207 | /// let result = { |
54a0048b SL |
208 | /// let mut wrapper = AssertUnwindSafe(&mut variable); |
209 | /// panic::catch_unwind(move || { | |
210 | /// **wrapper += other_capture; | |
9cc50fc6 SL |
211 | /// }) |
212 | /// }; | |
213 | /// // ... | |
214 | /// ``` | |
54a0048b | 215 | #[stable(feature = "catch_unwind", since = "1.9.0")] |
60c5eb7d | 216 | pub struct AssertUnwindSafe<T>(#[stable(feature = "catch_unwind", since = "1.9.0")] pub T); |
9cc50fc6 | 217 | |
54a0048b | 218 | // Implementations of the `UnwindSafe` trait: |
9cc50fc6 | 219 | // |
54a0048b SL |
220 | // * By default everything is unwind safe |
221 | // * pointers T contains mutability of some form are not unwind safe | |
9cc50fc6 | 222 | // * Unique, an owning pointer, lifts an implementation |
83c7162d | 223 | // * Types like Mutex/RwLock which are explicitly poisoned are unwind safe |
54a0048b | 224 | // * Our custom AssertUnwindSafe wrapper is indeed unwind safe |
2c00a5a8 | 225 | |
54a0048b | 226 | #[stable(feature = "catch_unwind", since = "1.9.0")] |
9fa01778 | 227 | impl<T: ?Sized> !UnwindSafe for &mut T {} |
54a0048b | 228 | #[stable(feature = "catch_unwind", since = "1.9.0")] |
9fa01778 | 229 | impl<T: RefUnwindSafe + ?Sized> UnwindSafe for &T {} |
54a0048b SL |
230 | #[stable(feature = "catch_unwind", since = "1.9.0")] |
231 | impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *const T {} | |
232 | #[stable(feature = "catch_unwind", since = "1.9.0")] | |
233 | impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *mut T {} | |
dfeec247 | 234 | #[unstable(feature = "ptr_internals", issue = "none")] |
32a655c1 | 235 | impl<T: UnwindSafe + ?Sized> UnwindSafe for Unique<T> {} |
2c00a5a8 XL |
236 | #[stable(feature = "nonnull", since = "1.25.0")] |
237 | impl<T: RefUnwindSafe + ?Sized> UnwindSafe for NonNull<T> {} | |
54a0048b SL |
238 | #[stable(feature = "catch_unwind", since = "1.9.0")] |
239 | impl<T: ?Sized> UnwindSafe for Mutex<T> {} | |
240 | #[stable(feature = "catch_unwind", since = "1.9.0")] | |
241 | impl<T: ?Sized> UnwindSafe for RwLock<T> {} | |
242 | #[stable(feature = "catch_unwind", since = "1.9.0")] | |
243 | impl<T> UnwindSafe for AssertUnwindSafe<T> {} | |
9cc50fc6 SL |
244 | |
245 | // not covered via the Shared impl above b/c the inner contents use | |
3157f602 | 246 | // Cell/AtomicUsize, but the usage here is unwind safe so we can lift the |
9cc50fc6 | 247 | // impl up one level to Arc/Rc itself |
54a0048b SL |
248 | #[stable(feature = "catch_unwind", since = "1.9.0")] |
249 | impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Rc<T> {} | |
250 | #[stable(feature = "catch_unwind", since = "1.9.0")] | |
251 | impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Arc<T> {} | |
9cc50fc6 | 252 | |
a7813a04 | 253 | // Pretty simple implementations for the `RefUnwindSafe` marker trait, |
2c00a5a8 | 254 | // basically just saying that `UnsafeCell` is the |
9cc50fc6 SL |
255 | // only thing which doesn't implement it (which then transitively applies to |
256 | // everything else). | |
54a0048b | 257 | #[stable(feature = "catch_unwind", since = "1.9.0")] |
54a0048b SL |
258 | impl<T: ?Sized> !RefUnwindSafe for UnsafeCell<T> {} |
259 | #[stable(feature = "catch_unwind", since = "1.9.0")] | |
260 | impl<T> RefUnwindSafe for AssertUnwindSafe<T> {} | |
54a0048b | 261 | |
5bcae85e SL |
262 | #[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")] |
263 | impl<T: ?Sized> RefUnwindSafe for Mutex<T> {} | |
264 | #[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")] | |
265 | impl<T: ?Sized> RefUnwindSafe for RwLock<T> {} | |
266 | ||
e74abb32 | 267 | #[cfg(target_has_atomic_load_store = "ptr")] |
c30ab7b3 SL |
268 | #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] |
269 | impl RefUnwindSafe for atomic::AtomicIsize {} | |
e74abb32 | 270 | #[cfg(target_has_atomic_load_store = "8")] |
1b1a35ee | 271 | #[stable(feature = "integer_atomics_stable", since = "1.34.0")] |
c30ab7b3 | 272 | impl RefUnwindSafe for atomic::AtomicI8 {} |
e74abb32 | 273 | #[cfg(target_has_atomic_load_store = "16")] |
1b1a35ee | 274 | #[stable(feature = "integer_atomics_stable", since = "1.34.0")] |
c30ab7b3 | 275 | impl RefUnwindSafe for atomic::AtomicI16 {} |
e74abb32 | 276 | #[cfg(target_has_atomic_load_store = "32")] |
1b1a35ee | 277 | #[stable(feature = "integer_atomics_stable", since = "1.34.0")] |
c30ab7b3 | 278 | impl RefUnwindSafe for atomic::AtomicI32 {} |
e74abb32 | 279 | #[cfg(target_has_atomic_load_store = "64")] |
1b1a35ee | 280 | #[stable(feature = "integer_atomics_stable", since = "1.34.0")] |
c30ab7b3 | 281 | impl RefUnwindSafe for atomic::AtomicI64 {} |
e74abb32 | 282 | #[cfg(target_has_atomic_load_store = "128")] |
a1dfa0c6 XL |
283 | #[unstable(feature = "integer_atomics", issue = "32976")] |
284 | impl RefUnwindSafe for atomic::AtomicI128 {} | |
c30ab7b3 | 285 | |
e74abb32 | 286 | #[cfg(target_has_atomic_load_store = "ptr")] |
c30ab7b3 SL |
287 | #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] |
288 | impl RefUnwindSafe for atomic::AtomicUsize {} | |
e74abb32 | 289 | #[cfg(target_has_atomic_load_store = "8")] |
1b1a35ee | 290 | #[stable(feature = "integer_atomics_stable", since = "1.34.0")] |
c30ab7b3 | 291 | impl RefUnwindSafe for atomic::AtomicU8 {} |
e74abb32 | 292 | #[cfg(target_has_atomic_load_store = "16")] |
1b1a35ee | 293 | #[stable(feature = "integer_atomics_stable", since = "1.34.0")] |
c30ab7b3 | 294 | impl RefUnwindSafe for atomic::AtomicU16 {} |
e74abb32 | 295 | #[cfg(target_has_atomic_load_store = "32")] |
1b1a35ee | 296 | #[stable(feature = "integer_atomics_stable", since = "1.34.0")] |
c30ab7b3 | 297 | impl RefUnwindSafe for atomic::AtomicU32 {} |
e74abb32 | 298 | #[cfg(target_has_atomic_load_store = "64")] |
1b1a35ee | 299 | #[stable(feature = "integer_atomics_stable", since = "1.34.0")] |
c30ab7b3 | 300 | impl RefUnwindSafe for atomic::AtomicU64 {} |
e74abb32 | 301 | #[cfg(target_has_atomic_load_store = "128")] |
a1dfa0c6 XL |
302 | #[unstable(feature = "integer_atomics", issue = "32976")] |
303 | impl RefUnwindSafe for atomic::AtomicU128 {} | |
c30ab7b3 | 304 | |
e74abb32 | 305 | #[cfg(target_has_atomic_load_store = "8")] |
c30ab7b3 SL |
306 | #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] |
307 | impl RefUnwindSafe for atomic::AtomicBool {} | |
308 | ||
e74abb32 | 309 | #[cfg(target_has_atomic_load_store = "ptr")] |
c30ab7b3 SL |
310 | #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] |
311 | impl<T> RefUnwindSafe for atomic::AtomicPtr<T> {} | |
312 | ||
48663c56 XL |
313 | // https://github.com/rust-lang/rust/issues/62301 |
314 | #[stable(feature = "hashbrown", since = "1.36.0")] | |
315 | impl<K, V, S> UnwindSafe for collections::HashMap<K, V, S> | |
60c5eb7d XL |
316 | where |
317 | K: UnwindSafe, | |
318 | V: UnwindSafe, | |
319 | S: UnwindSafe, | |
320 | { | |
321 | } | |
48663c56 | 322 | |
54a0048b SL |
323 | #[stable(feature = "catch_unwind", since = "1.9.0")] |
324 | impl<T> Deref for AssertUnwindSafe<T> { | |
325 | type Target = T; | |
9cc50fc6 | 326 | |
54a0048b SL |
327 | fn deref(&self) -> &T { |
328 | &self.0 | |
329 | } | |
330 | } | |
331 | ||
332 | #[stable(feature = "catch_unwind", since = "1.9.0")] | |
333 | impl<T> DerefMut for AssertUnwindSafe<T> { | |
334 | fn deref_mut(&mut self) -> &mut T { | |
335 | &mut self.0 | |
336 | } | |
337 | } | |
338 | ||
339 | #[stable(feature = "catch_unwind", since = "1.9.0")] | |
340 | impl<R, F: FnOnce() -> R> FnOnce<()> for AssertUnwindSafe<F> { | |
341 | type Output = R; | |
342 | ||
343 | extern "rust-call" fn call_once(self, _args: ()) -> R { | |
344 | (self.0)() | |
345 | } | |
346 | } | |
347 | ||
8bb4bdeb | 348 | #[stable(feature = "std_debug", since = "1.16.0")] |
32a655c1 | 349 | impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> { |
532ac7d7 | 350 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
60c5eb7d | 351 | f.debug_tuple("AssertUnwindSafe").field(&self.0).finish() |
32a655c1 SL |
352 | } |
353 | } | |
354 | ||
48663c56 | 355 | #[stable(feature = "futures_api", since = "1.36.0")] |
9fa01778 | 356 | impl<F: Future> Future for AssertUnwindSafe<F> { |
94b46f34 XL |
357 | type Output = F::Output; |
358 | ||
532ac7d7 | 359 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
0bf4aa26 | 360 | let pinned_field = unsafe { Pin::map_unchecked_mut(self, |x| &mut x.0) }; |
532ac7d7 | 361 | F::poll(pinned_field, cx) |
94b46f34 XL |
362 | } |
363 | } | |
364 | ||
5869c6ff XL |
365 | #[unstable(feature = "async_stream", issue = "79024")] |
366 | impl<S: Stream> Stream for AssertUnwindSafe<S> { | |
367 | type Item = S::Item; | |
368 | ||
369 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<S::Item>> { | |
370 | unsafe { self.map_unchecked_mut(|x| &mut x.0) }.poll_next(cx) | |
371 | } | |
372 | ||
373 | fn size_hint(&self) -> (usize, Option<usize>) { | |
374 | self.0.size_hint() | |
375 | } | |
376 | } | |
377 | ||
54a0048b | 378 | /// Invokes a closure, capturing the cause of an unwinding panic if one occurs. |
9cc50fc6 SL |
379 | /// |
380 | /// This function will return `Ok` with the closure's result if the closure | |
381 | /// does not panic, and will return `Err(cause)` if the closure panics. The | |
382 | /// `cause` returned is the object with which panic was originally invoked. | |
383 | /// | |
384 | /// It is currently undefined behavior to unwind from Rust code into foreign | |
385 | /// code, so this function is particularly useful when Rust is called from | |
386 | /// another language (normally C). This can run arbitrary Rust code, capturing a | |
387 | /// panic and allowing a graceful handling of the error. | |
388 | /// | |
389 | /// It is **not** recommended to use this function for a general try/catch | |
83c7162d | 390 | /// mechanism. The [`Result`] type is more appropriate to use for functions that |
54a0048b | 391 | /// can fail on a regular basis. Additionally, this function is not guaranteed |
a7813a04 | 392 | /// to catch all panics, see the "Notes" section below. |
54a0048b | 393 | /// |
83c7162d | 394 | /// The closure provided is required to adhere to the [`UnwindSafe`] trait to ensure |
54a0048b SL |
395 | /// that all captured variables are safe to cross this boundary. The purpose of |
396 | /// this bound is to encode the concept of [exception safety][rfc] in the type | |
397 | /// system. Most usage of this function should not need to worry about this | |
3157f602 | 398 | /// bound as programs are naturally unwind safe without `unsafe` code. If it |
83c7162d XL |
399 | /// becomes a problem the [`AssertUnwindSafe`] wrapper struct can be used to quickly |
400 | /// assert that the usage here is indeed unwind safe. | |
401 | /// | |
9cc50fc6 SL |
402 | /// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md |
403 | /// | |
54a0048b SL |
404 | /// # Notes |
405 | /// | |
406 | /// Note that this function **may not catch all panics** in Rust. A panic in | |
407 | /// Rust is not always implemented via unwinding, but can be implemented by | |
408 | /// aborting the process as well. This function *only* catches unwinding panics, | |
409 | /// not those that abort the process. | |
410 | /// | |
1b1a35ee XL |
411 | /// Also note that unwinding into Rust code with a foreign exception (e.g. a |
412 | /// an exception thrown from C++ code) is undefined behavior. | |
413 | /// | |
9cc50fc6 SL |
414 | /// # Examples |
415 | /// | |
416 | /// ``` | |
9cc50fc6 SL |
417 | /// use std::panic; |
418 | /// | |
54a0048b | 419 | /// let result = panic::catch_unwind(|| { |
9cc50fc6 SL |
420 | /// println!("hello!"); |
421 | /// }); | |
422 | /// assert!(result.is_ok()); | |
423 | /// | |
54a0048b | 424 | /// let result = panic::catch_unwind(|| { |
9cc50fc6 SL |
425 | /// panic!("oh no!"); |
426 | /// }); | |
427 | /// assert!(result.is_err()); | |
428 | /// ``` | |
54a0048b SL |
429 | #[stable(feature = "catch_unwind", since = "1.9.0")] |
430 | pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> { | |
60c5eb7d | 431 | unsafe { panicking::r#try(f) } |
9cc50fc6 SL |
432 | } |
433 | ||
a7813a04 | 434 | /// Triggers a panic without invoking the panic hook. |
9cc50fc6 | 435 | /// |
83c7162d | 436 | /// This is designed to be used in conjunction with [`catch_unwind`] to, for |
54a0048b SL |
437 | /// example, carry a panic across a layer of C code. |
438 | /// | |
439 | /// # Notes | |
440 | /// | |
441 | /// Note that panics in Rust are not always implemented via unwinding, but they | |
442 | /// may be implemented by aborting the process. If this function is called when | |
443 | /// panics are implemented this way then this function will abort the process, | |
444 | /// not trigger an unwind. | |
9cc50fc6 SL |
445 | /// |
446 | /// # Examples | |
447 | /// | |
448 | /// ```should_panic | |
9cc50fc6 SL |
449 | /// use std::panic; |
450 | /// | |
54a0048b | 451 | /// let result = panic::catch_unwind(|| { |
9cc50fc6 SL |
452 | /// panic!("oh no!"); |
453 | /// }); | |
454 | /// | |
455 | /// if let Err(err) = result { | |
54a0048b | 456 | /// panic::resume_unwind(err); |
9cc50fc6 SL |
457 | /// } |
458 | /// ``` | |
54a0048b | 459 | #[stable(feature = "resume_unwind", since = "1.9.0")] |
8faf50e0 | 460 | pub fn resume_unwind(payload: Box<dyn Any + Send>) -> ! { |
60c5eb7d | 461 | panicking::rust_panic_without_hook(payload) |
54a0048b | 462 | } |
1b1a35ee XL |
463 | |
464 | #[cfg(test)] | |
465 | mod tests; |