]>
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 | 5 | use crate::any::Any; |
48663c56 | 6 | use crate::collections; |
532ac7d7 | 7 | use crate::panicking; |
94222f64 | 8 | use crate::sync::{Mutex, RwLock}; |
532ac7d7 | 9 | use crate::thread::Result; |
9cc50fc6 | 10 | |
5869c6ff XL |
11 | #[doc(hidden)] |
12 | #[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")] | |
94222f64 | 13 | #[allow_internal_unstable(libstd_sys_internals, const_format_args)] |
5869c6ff XL |
14 | #[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_2015_macro")] |
15 | #[rustc_macro_transparency = "semitransparent"] | |
16 | pub macro panic_2015 { | |
17 | () => ({ | |
18 | $crate::rt::begin_panic("explicit panic") | |
19 | }), | |
20 | ($msg:expr $(,)?) => ({ | |
21 | $crate::rt::begin_panic($msg) | |
22 | }), | |
23 | ($fmt:expr, $($arg:tt)+) => ({ | |
94222f64 | 24 | $crate::rt::begin_panic_fmt(&$crate::const_format_args!($fmt, $($arg)+)) |
5869c6ff XL |
25 | }), |
26 | } | |
27 | ||
28 | #[doc(hidden)] | |
29 | #[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")] | |
30 | pub use core::panic::panic_2021; | |
31 | ||
a7813a04 | 32 | #[stable(feature = "panic_hooks", since = "1.10.0")] |
60c5eb7d | 33 | pub use crate::panicking::{set_hook, take_hook}; |
0531ce1d XL |
34 | |
35 | #[stable(feature = "panic_hooks", since = "1.10.0")] | |
60c5eb7d | 36 | pub use core::panic::{Location, PanicInfo}; |
54a0048b | 37 | |
94222f64 XL |
38 | #[stable(feature = "catch_unwind", since = "1.9.0")] |
39 | pub use core::panic::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe}; | |
40 | ||
29967ef6 XL |
41 | /// Panic the current thread with the given message as the panic payload. |
42 | /// | |
43 | /// The message can be of any (`Any + Send`) type, not just strings. | |
44 | /// | |
45 | /// The message is wrapped in a `Box<'static + Any + Send>`, which can be | |
46 | /// accessed later using [`PanicInfo::payload`]. | |
47 | /// | |
48 | /// See the [`panic!`] macro for more information about panicking. | |
5869c6ff | 49 | #[stable(feature = "panic_any", since = "1.51.0")] |
29967ef6 | 50 | #[inline] |
17df50a5 | 51 | #[track_caller] |
5869c6ff | 52 | pub fn panic_any<M: 'static + Any + Send>(msg: M) -> ! { |
29967ef6 XL |
53 | crate::panicking::begin_panic(msg); |
54 | } | |
55 | ||
54a0048b SL |
56 | #[stable(feature = "catch_unwind", since = "1.9.0")] |
57 | impl<T: ?Sized> UnwindSafe for Mutex<T> {} | |
58 | #[stable(feature = "catch_unwind", since = "1.9.0")] | |
59 | impl<T: ?Sized> UnwindSafe for RwLock<T> {} | |
54a0048b | 60 | |
5bcae85e SL |
61 | #[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")] |
62 | impl<T: ?Sized> RefUnwindSafe for Mutex<T> {} | |
63 | #[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")] | |
64 | impl<T: ?Sized> RefUnwindSafe for RwLock<T> {} | |
65 | ||
48663c56 XL |
66 | // https://github.com/rust-lang/rust/issues/62301 |
67 | #[stable(feature = "hashbrown", since = "1.36.0")] | |
68 | impl<K, V, S> UnwindSafe for collections::HashMap<K, V, S> | |
60c5eb7d XL |
69 | where |
70 | K: UnwindSafe, | |
71 | V: UnwindSafe, | |
72 | S: UnwindSafe, | |
73 | { | |
74 | } | |
48663c56 | 75 | |
54a0048b | 76 | /// Invokes a closure, capturing the cause of an unwinding panic if one occurs. |
9cc50fc6 SL |
77 | /// |
78 | /// This function will return `Ok` with the closure's result if the closure | |
79 | /// does not panic, and will return `Err(cause)` if the closure panics. The | |
80 | /// `cause` returned is the object with which panic was originally invoked. | |
81 | /// | |
82 | /// It is currently undefined behavior to unwind from Rust code into foreign | |
83 | /// code, so this function is particularly useful when Rust is called from | |
84 | /// another language (normally C). This can run arbitrary Rust code, capturing a | |
85 | /// panic and allowing a graceful handling of the error. | |
86 | /// | |
87 | /// It is **not** recommended to use this function for a general try/catch | |
83c7162d | 88 | /// mechanism. The [`Result`] type is more appropriate to use for functions that |
54a0048b | 89 | /// can fail on a regular basis. Additionally, this function is not guaranteed |
a7813a04 | 90 | /// to catch all panics, see the "Notes" section below. |
54a0048b | 91 | /// |
83c7162d | 92 | /// The closure provided is required to adhere to the [`UnwindSafe`] trait to ensure |
54a0048b SL |
93 | /// that all captured variables are safe to cross this boundary. The purpose of |
94 | /// this bound is to encode the concept of [exception safety][rfc] in the type | |
95 | /// system. Most usage of this function should not need to worry about this | |
3157f602 | 96 | /// bound as programs are naturally unwind safe without `unsafe` code. If it |
83c7162d XL |
97 | /// becomes a problem the [`AssertUnwindSafe`] wrapper struct can be used to quickly |
98 | /// assert that the usage here is indeed unwind safe. | |
99 | /// | |
9cc50fc6 SL |
100 | /// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md |
101 | /// | |
54a0048b SL |
102 | /// # Notes |
103 | /// | |
94222f64 | 104 | /// Note that this function **might not catch all panics** in Rust. A panic in |
54a0048b SL |
105 | /// Rust is not always implemented via unwinding, but can be implemented by |
106 | /// aborting the process as well. This function *only* catches unwinding panics, | |
107 | /// not those that abort the process. | |
108 | /// | |
6a06907d | 109 | /// Also note that unwinding into Rust code with a foreign exception (e.g. |
1b1a35ee XL |
110 | /// an exception thrown from C++ code) is undefined behavior. |
111 | /// | |
9cc50fc6 SL |
112 | /// # Examples |
113 | /// | |
114 | /// ``` | |
9cc50fc6 SL |
115 | /// use std::panic; |
116 | /// | |
54a0048b | 117 | /// let result = panic::catch_unwind(|| { |
9cc50fc6 SL |
118 | /// println!("hello!"); |
119 | /// }); | |
120 | /// assert!(result.is_ok()); | |
121 | /// | |
54a0048b | 122 | /// let result = panic::catch_unwind(|| { |
9cc50fc6 SL |
123 | /// panic!("oh no!"); |
124 | /// }); | |
125 | /// assert!(result.is_err()); | |
126 | /// ``` | |
54a0048b SL |
127 | #[stable(feature = "catch_unwind", since = "1.9.0")] |
128 | pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> { | |
60c5eb7d | 129 | unsafe { panicking::r#try(f) } |
9cc50fc6 SL |
130 | } |
131 | ||
a7813a04 | 132 | /// Triggers a panic without invoking the panic hook. |
9cc50fc6 | 133 | /// |
83c7162d | 134 | /// This is designed to be used in conjunction with [`catch_unwind`] to, for |
54a0048b SL |
135 | /// example, carry a panic across a layer of C code. |
136 | /// | |
137 | /// # Notes | |
138 | /// | |
139 | /// Note that panics in Rust are not always implemented via unwinding, but they | |
140 | /// may be implemented by aborting the process. If this function is called when | |
141 | /// panics are implemented this way then this function will abort the process, | |
142 | /// not trigger an unwind. | |
9cc50fc6 SL |
143 | /// |
144 | /// # Examples | |
145 | /// | |
146 | /// ```should_panic | |
9cc50fc6 SL |
147 | /// use std::panic; |
148 | /// | |
54a0048b | 149 | /// let result = panic::catch_unwind(|| { |
9cc50fc6 SL |
150 | /// panic!("oh no!"); |
151 | /// }); | |
152 | /// | |
153 | /// if let Err(err) = result { | |
54a0048b | 154 | /// panic::resume_unwind(err); |
9cc50fc6 SL |
155 | /// } |
156 | /// ``` | |
54a0048b | 157 | #[stable(feature = "resume_unwind", since = "1.9.0")] |
8faf50e0 | 158 | pub fn resume_unwind(payload: Box<dyn Any + Send>) -> ! { |
60c5eb7d | 159 | panicking::rust_panic_without_hook(payload) |
54a0048b | 160 | } |
1b1a35ee | 161 | |
17df50a5 XL |
162 | /// Make all future panics abort directly without running the panic hook or unwinding. |
163 | /// | |
164 | /// There is no way to undo this; the effect lasts until the process exits or | |
165 | /// execs (or the equivalent). | |
166 | /// | |
167 | /// # Use after fork | |
168 | /// | |
169 | /// This function is particularly useful for calling after `libc::fork`. After `fork`, in a | |
170 | /// multithreaded program it is (on many platforms) not safe to call the allocator. It is also | |
171 | /// generally highly undesirable for an unwind to unwind past the `fork`, because that results in | |
172 | /// the unwind propagating to code that was only ever expecting to run in the parent. | |
173 | /// | |
174 | /// `panic::always_abort()` helps avoid both of these. It directly avoids any further unwinding, | |
175 | /// and if there is a panic, the abort will occur without allocating provided that the arguments to | |
176 | /// panic can be formatted without allocating. | |
177 | /// | |
178 | /// Examples | |
179 | /// | |
180 | /// ```no_run | |
181 | /// #![feature(panic_always_abort)] | |
182 | /// use std::panic; | |
183 | /// | |
184 | /// panic::always_abort(); | |
185 | /// | |
186 | /// let _ = panic::catch_unwind(|| { | |
187 | /// panic!("inside the catch"); | |
188 | /// }); | |
189 | /// | |
190 | /// // We will have aborted already, due to the panic. | |
191 | /// unreachable!(); | |
192 | /// ``` | |
193 | #[unstable(feature = "panic_always_abort", issue = "84438")] | |
194 | pub fn always_abort() { | |
195 | crate::panicking::panic_count::set_always_abort(); | |
196 | } | |
197 | ||
1b1a35ee XL |
198 | #[cfg(test)] |
199 | mod tests; |