]> git.proxmox.com Git - rustc.git/blame - src/libstd/panicking.rs
New upstream version 1.44.1+dfsg1
[rustc.git] / src / libstd / panicking.rs
CommitLineData
a7813a04
XL
1//! Implementation of various bits and pieces of the `panic!` macro and
2//! associated runtime pieces.
3//!
4//! Specifically, this module contains the implementation of:
5//!
6//! * Panic hooks
7//! * Executing a panic up to doing the actual implementation
8//! * Shims around "try"
9
dfeec247 10use core::panic::{BoxMeUp, Location, PanicInfo};
532ac7d7
XL
11
12use crate::any::Any;
13use crate::fmt;
14use crate::intrinsics;
e74abb32 15use crate::mem::{self, ManuallyDrop};
dfeec247 16use crate::process;
e74abb32 17use crate::sync::atomic::{AtomicBool, Ordering};
532ac7d7 18use crate::sys::stdio::panic_output;
dfeec247 19use crate::sys_common::backtrace::{self, RustBacktrace};
532ac7d7 20use crate::sys_common::rwlock::RWLock;
e74abb32 21use crate::sys_common::{thread_info, util};
532ac7d7
XL
22use crate::thread;
23
24#[cfg(not(test))]
25use crate::io::set_panic;
26// make sure to use the stderr output configured
27// by libtest in the real copy of std
28#[cfg(test)]
29use realstd::io::set_panic;
1a4d82fc 30
a7813a04
XL
31// Binary interface to the panic runtime that the standard library depends on.
32//
33// The standard library is tagged with `#![needs_panic_runtime]` (introduced in
34// RFC 1513) to indicate that it requires some other crate tagged with
35// `#![panic_runtime]` to exist somewhere. Each panic runtime is intended to
36// implement these symbols (with the same signatures) so we can get matched up
37// to them.
38//
39// One day this may look a little less ad-hoc with the compiler helping out to
40// hook up these functions, but it is not this day!
41#[allow(improper_ctypes)]
dfeec247 42extern "C" {
ba9703b0 43 fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static);
60c5eb7d
XL
44
45 /// `payload` is actually a `*mut &mut dyn BoxMeUp` but that would cause FFI warnings.
46 /// It cannot be `Box<dyn BoxMeUp>` because the other end of this call does not depend
47 /// on liballoc, and thus cannot use `Box`.
83c7162d
XL
48 #[unwind(allowed)]
49 fn __rust_start_panic(payload: usize) -> u32;
a7813a04
XL
50}
51
dfeec247
XL
52/// This function is called by the panic runtime if FFI code catches a Rust
53/// panic but doesn't rethrow it. We don't support this case since it messes
54/// with our panic count.
55#[cfg(not(test))]
56#[rustc_std_internal_symbol]
57extern "C" fn __rust_drop_panic() -> ! {
58 rtabort!("Rust panics must be rethrown");
59}
60
9cc50fc6 61#[derive(Copy, Clone)]
54a0048b 62enum Hook {
9cc50fc6 63 Default,
532ac7d7 64 Custom(*mut (dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send)),
9cc50fc6
SL
65}
66
a7813a04 67static HOOK_LOCK: RWLock = RWLock::new();
54a0048b 68static mut HOOK: Hook = Hook::Default;
9cc50fc6 69
54a0048b 70/// Registers a custom panic hook, replacing any that was previously registered.
9cc50fc6 71///
a7813a04
XL
72/// The panic hook is invoked when a thread panics, but before the panic runtime
73/// is invoked. As such, the hook will run with both the aborting and unwinding
74/// runtimes. The default hook prints a message to standard error and generates
75/// a backtrace if requested, but this behavior can be customized with the
83c7162d
XL
76/// `set_hook` and [`take_hook`] functions.
77///
78/// [`take_hook`]: ./fn.take_hook.html
9cc50fc6 79///
54a0048b 80/// The hook is provided with a `PanicInfo` struct which contains information
9cc50fc6
SL
81/// about the origin of the panic, including the payload passed to `panic!` and
82/// the source code location from which the panic originated.
83///
54a0048b 84/// The panic hook is a global resource.
9cc50fc6
SL
85///
86/// # Panics
87///
88/// Panics if called from a panicking thread.
9e0c209e
SL
89///
90/// # Examples
91///
92/// The following will print "Custom panic hook":
93///
94/// ```should_panic
95/// use std::panic;
96///
97/// panic::set_hook(Box::new(|_| {
98/// println!("Custom panic hook");
99/// }));
100///
101/// panic!("Normal panic");
102/// ```
a7813a04 103#[stable(feature = "panic_hooks", since = "1.10.0")]
532ac7d7 104pub fn set_hook(hook: Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>) {
9cc50fc6 105 if thread::panicking() {
54a0048b 106 panic!("cannot modify the panic hook from a panicking thread");
9cc50fc6
SL
107 }
108
9cc50fc6 109 unsafe {
a7813a04 110 HOOK_LOCK.write();
54a0048b
SL
111 let old_hook = HOOK;
112 HOOK = Hook::Custom(Box::into_raw(hook));
a7813a04 113 HOOK_LOCK.write_unlock();
9cc50fc6 114
54a0048b 115 if let Hook::Custom(ptr) = old_hook {
dfeec247
XL
116 #[allow(unused_must_use)]
117 {
dc9dc135
XL
118 Box::from_raw(ptr);
119 }
9cc50fc6
SL
120 }
121 }
122}
123
54a0048b 124/// Unregisters the current panic hook, returning it.
9cc50fc6 125///
83c7162d
XL
126/// *See also the function [`set_hook`].*
127///
128/// [`set_hook`]: ./fn.set_hook.html
129///
54a0048b 130/// If no custom hook is registered, the default hook will be returned.
9cc50fc6
SL
131///
132/// # Panics
133///
134/// Panics if called from a panicking thread.
9e0c209e
SL
135///
136/// # Examples
137///
138/// The following will print "Normal panic":
139///
140/// ```should_panic
141/// use std::panic;
142///
143/// panic::set_hook(Box::new(|_| {
144/// println!("Custom panic hook");
145/// }));
146///
147/// let _ = panic::take_hook();
148///
149/// panic!("Normal panic");
150/// ```
a7813a04 151#[stable(feature = "panic_hooks", since = "1.10.0")]
532ac7d7 152pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
9cc50fc6 153 if thread::panicking() {
54a0048b 154 panic!("cannot modify the panic hook from a panicking thread");
9cc50fc6
SL
155 }
156
157 unsafe {
a7813a04 158 HOOK_LOCK.write();
54a0048b
SL
159 let hook = HOOK;
160 HOOK = Hook::Default;
a7813a04 161 HOOK_LOCK.write_unlock();
9cc50fc6 162
54a0048b
SL
163 match hook {
164 Hook::Default => Box::new(default_hook),
476ff2be 165 Hook::Custom(ptr) => Box::from_raw(ptr),
9cc50fc6
SL
166 }
167 }
168}
169
532ac7d7 170fn default_hook(info: &PanicInfo<'_>) {
9cc50fc6
SL
171 // If this is a double panic, make sure that we print a backtrace
172 // for this panic. Otherwise only print it if logging is enabled.
e74abb32
XL
173 let backtrace_env = if update_panic_count(0) >= 2 {
174 RustBacktrace::Print(backtrace_rs::PrintFmt::Full)
e1599b0c 175 } else {
e74abb32 176 backtrace::rust_backtrace_env()
5bcae85e 177 };
9cc50fc6 178
dc9dc135
XL
179 // The current implementation always returns `Some`.
180 let location = info.location().unwrap();
9cc50fc6 181
0531ce1d 182 let msg = match info.payload().downcast_ref::<&'static str>() {
1a4d82fc 183 Some(s) => *s,
0531ce1d 184 None => match info.payload().downcast_ref::<String>() {
85aaf69f 185 Some(s) => &s[..],
1a4d82fc 186 None => "Box<Any>",
dfeec247 187 },
1a4d82fc 188 };
d9579d0f
AL
189 let thread = thread_info::current_thread();
190 let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
b039eaaf 191
532ac7d7 192 let write = |err: &mut dyn crate::io::Write| {
dfeec247 193 let _ = writeln!(err, "thread '{}' panicked at '{}', {}", name, msg, location);
7453a54e 194
e74abb32 195 static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
5bcae85e 196
e74abb32
XL
197 match backtrace_env {
198 RustBacktrace::Print(format) => drop(backtrace::print(err, format)),
199 RustBacktrace::Disabled => {}
200 RustBacktrace::RuntimeDisabled => {
201 if FIRST_PANIC.swap(false, Ordering::SeqCst) {
dfeec247
XL
202 let _ = writeln!(
203 err,
204 "note: run with `RUST_BACKTRACE=1` \
205 environment variable to display a backtrace"
206 );
e74abb32 207 }
5bcae85e 208 }
b039eaaf
SL
209 }
210 };
211
532ac7d7
XL
212 if let Some(mut local) = set_panic(None) {
213 // NB. In `cfg(test)` this uses the forwarding impl
214 // for `Box<dyn (::realstd::io::Write) + Send>`.
215 write(&mut local);
216 set_panic(Some(local));
0731742a
XL
217 } else if let Some(mut out) = panic_output() {
218 write(&mut out);
1a4d82fc 219 }
b039eaaf 220}
1a4d82fc 221
5bcae85e
SL
222#[cfg(not(test))]
223#[doc(hidden)]
dfeec247 224#[unstable(feature = "update_panic_count", issue = "none")]
5bcae85e 225pub fn update_panic_count(amt: isize) -> usize {
532ac7d7 226 use crate::cell::Cell;
5bcae85e
SL
227 thread_local! { static PANIC_COUNT: Cell<usize> = Cell::new(0) }
228
229 PANIC_COUNT.with(|c| {
230 let next = (c.get() as isize + amt) as usize;
231 c.set(next);
e74abb32 232 next
5bcae85e
SL
233 })
234}
235
236#[cfg(test)]
237pub use realstd::rt::update_panic_count;
238
a7813a04 239/// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
532ac7d7 240pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
8bb4bdeb 241 union Data<F, R> {
e74abb32
XL
242 f: ManuallyDrop<F>,
243 r: ManuallyDrop<R>,
ba9703b0 244 p: ManuallyDrop<Box<dyn Any + Send>>,
5bcae85e 245 }
a7813a04 246
5bcae85e 247 // We do some sketchy operations with ownership here for the sake of
ba9703b0
XL
248 // performance. We can only pass pointers down to `do_call` (can't pass
249 // objects by value), so we do all the ownership tracking here manually
250 // using a union.
5bcae85e 251 //
8bb4bdeb 252 // We go through a transition where:
5bcae85e 253 //
ba9703b0 254 // * First, we set the data field `f` to be the argumentless closure that we're going to call.
5bcae85e 255 // * When we make the function call, the `do_call` function below, we take
ba9703b0 256 // ownership of the function pointer. At this point the `data` union is
8bb4bdeb 257 // entirely uninitialized.
5bcae85e 258 // * If the closure successfully returns, we write the return value into the
ba9703b0
XL
259 // data's return slot (field `r`).
260 // * If the closure panics (`do_catch` below), we write the panic payload into field `p`.
261 // * Finally, when we come back out of the `try` intrinsic we're
5bcae85e
SL
262 // in one of two states:
263 //
264 // 1. The closure didn't panic, in which case the return value was
ba9703b0
XL
265 // filled in. We move it out of `data.r` and return it.
266 // 2. The closure panicked, in which case the panic payload was
267 // filled in. We move it out of `data.p` and return it.
5bcae85e
SL
268 //
269 // Once we stack all that together we should have the "most efficient'
270 // method of calling a catch panic whilst juggling ownership.
dfeec247 271 let mut data = Data { f: ManuallyDrop::new(f) };
b039eaaf 272
ba9703b0
XL
273 let data_ptr = &mut data as *mut _ as *mut u8;
274 return if do_try(do_call::<F, R>, data_ptr, do_catch::<F, R>) == 0 {
e74abb32 275 Ok(ManuallyDrop::into_inner(data.r))
5bcae85e 276 } else {
ba9703b0 277 Err(ManuallyDrop::into_inner(data.p))
5bcae85e 278 };
a7813a04 279
ba9703b0
XL
280 // Compatibility wrapper around the try intrinsic for bootstrap.
281 //
282 // We also need to mark it #[inline(never)] to work around a bug on MinGW
283 // targets: the unwinding implementation was relying on UB, but this only
284 // becomes a problem in practice if inlining is involved.
285 #[cfg(not(bootstrap))]
286 use intrinsics::r#try as do_try;
287 #[cfg(bootstrap)]
288 #[inline(never)]
289 unsafe fn do_try(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32 {
290 use crate::mem::MaybeUninit;
291 #[cfg(target_env = "msvc")]
292 type TryPayload = [u64; 2];
293 #[cfg(not(target_env = "msvc"))]
294 type TryPayload = *mut u8;
295
296 let mut payload: MaybeUninit<TryPayload> = MaybeUninit::uninit();
297 let payload_ptr = payload.as_mut_ptr() as *mut u8;
298 let r = intrinsics::r#try(try_fn, data, payload_ptr);
299 if r != 0 {
300 #[cfg(target_env = "msvc")]
301 {
302 catch_fn(data, payload_ptr)
303 }
304 #[cfg(not(target_env = "msvc"))]
305 {
306 catch_fn(data, payload.assume_init())
307 }
308 }
309 r
310 }
311
312 // We consider unwinding to be rare, so mark this function as cold. However,
313 // do not mark it no-inline -- that decision is best to leave to the
314 // optimizer (in most cases this function is not inlined even as a normal,
315 // non-cold function, though, as of the writing of this comment).
316 #[cold]
317 unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send + 'static> {
318 let obj = Box::from_raw(__rust_panic_cleanup(payload));
319 update_panic_count(-1);
320 obj
321 }
322
323 // See comment on do_try above for why #[inline(never)] is needed on bootstrap.
324 #[cfg_attr(bootstrap, inline(never))]
325 #[cfg_attr(not(bootstrap), inline)]
5bcae85e
SL
326 fn do_call<F: FnOnce() -> R, R>(data: *mut u8) {
327 unsafe {
328 let data = data as *mut Data<F, R>;
e74abb32
XL
329 let data = &mut (*data);
330 let f = ManuallyDrop::take(&mut data.f);
331 data.r = ManuallyDrop::new(f());
5bcae85e 332 }
a7813a04 333 }
ba9703b0
XL
334
335 // We *do* want this part of the catch to be inlined: this allows the
336 // compiler to properly track accesses to the Data union and optimize it
337 // away most of the time.
338 #[inline]
339 fn do_catch<F: FnOnce() -> R, R>(data: *mut u8, payload: *mut u8) {
340 unsafe {
341 let data = data as *mut Data<F, R>;
342 let data = &mut (*data);
343 let obj = cleanup(payload);
344 data.p = ManuallyDrop::new(obj);
345 }
346 }
a7813a04
XL
347}
348
349/// Determines whether the current thread is unwinding because of panic.
350pub fn panicking() -> bool {
5bcae85e 351 update_panic_count(0) != 0
a7813a04
XL
352}
353
a7813a04
XL
354/// The entry point for panicking with a formatted message.
355///
356/// This is designed to reduce the amount of code required at the call
357/// site as much as possible (so that `panic!()` has as low an impact
358/// on (e.g.) the inlining of other functions as possible), by moving
359/// the actual formatting into this shared place.
dfeec247 360#[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "none")]
a1dfa0c6
XL
361#[cold]
362// If panic_immediate_abort, inline the abort call,
363// otherwise avoid inlining because of it is cold path.
dfeec247
XL
364#[cfg_attr(not(feature = "panic_immediate_abort"), track_caller)]
365#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
366#[cfg_attr(feature = "panic_immediate_abort", inline)]
367pub fn begin_panic_fmt(msg: &fmt::Arguments<'_>) -> ! {
a1dfa0c6
XL
368 if cfg!(feature = "panic_immediate_abort") {
369 unsafe { intrinsics::abort() }
370 }
371
dfeec247 372 let info = PanicInfo::internal_constructor(Some(msg), Location::caller());
60c5eb7d 373 begin_panic_handler(&info)
94b46f34 374}
83c7162d 375
60c5eb7d
XL
376/// Entry point of panics from the libcore crate (`panic_impl` lang item).
377#[cfg_attr(not(test), panic_handler)]
378#[unwind(allowed)]
379pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
8faf50e0
XL
380 struct PanicPayload<'a> {
381 inner: &'a fmt::Arguments<'a>,
382 string: Option<String>,
83c7162d
XL
383 }
384
8faf50e0
XL
385 impl<'a> PanicPayload<'a> {
386 fn new(inner: &'a fmt::Arguments<'a>) -> PanicPayload<'a> {
387 PanicPayload { inner, string: None }
388 }
83c7162d 389
8faf50e0 390 fn fill(&mut self) -> &mut String {
532ac7d7 391 use crate::fmt::Write;
83c7162d 392
8faf50e0 393 let inner = self.inner;
60c5eb7d 394 // Lazily, the first time this gets called, run the actual string formatting.
8faf50e0
XL
395 self.string.get_or_insert_with(|| {
396 let mut s = String::new();
397 drop(s.write_fmt(*inner));
398 s
399 })
400 }
94b46f34 401 }
83c7162d 402
8faf50e0 403 unsafe impl<'a> BoxMeUp for PanicPayload<'a> {
60c5eb7d 404 fn take_box(&mut self) -> *mut (dyn Any + Send) {
dfeec247
XL
405 // We do two allocations here, unfortunately. But (a) they're required with the current
406 // scheme, and (b) we don't handle panic + OOM properly anyway (see comment in
407 // begin_panic below).
416331ca 408 let contents = mem::take(self.fill());
8faf50e0
XL
409 Box::into_raw(Box::new(contents))
410 }
041b39d2 411
8faf50e0
XL
412 fn get(&mut self) -> &(dyn Any + Send) {
413 self.fill()
414 }
415 }
94b46f34 416
94b46f34
XL
417 let loc = info.location().unwrap(); // The current implementation always returns Some
418 let msg = info.message().unwrap(); // The current implementation always returns Some
dfeec247 419 rust_panic_with_hook(&mut PanicPayload::new(msg), info.message(), loc);
94b46f34
XL
420}
421
60c5eb7d
XL
422/// This is the entry point of panicking for the non-format-string variants of
423/// panic!() and assert!(). In particular, this is the only entry point that supports
424/// arbitrary payloads, not just format strings.
dfeec247
XL
425#[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "none")]
426#[cfg_attr(not(test), lang = "begin_panic")]
427// lang item for CTFE panic support
a1dfa0c6
XL
428// never inline unless panic_immediate_abort to avoid code
429// bloat at the call sites as much as possible
dfeec247 430#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
a1dfa0c6 431#[cold]
dfeec247 432#[track_caller]
74b04a01 433pub fn begin_panic<M: Any + Send>(msg: M) -> ! {
a1dfa0c6
XL
434 if cfg!(feature = "panic_immediate_abort") {
435 unsafe { intrinsics::abort() }
436 }
437
dfeec247 438 rust_panic_with_hook(&mut PanicPayload::new(msg), None, Location::caller());
83c7162d
XL
439
440 struct PanicPayload<A> {
441 inner: Option<A>,
442 }
443
444 impl<A: Send + 'static> PanicPayload<A> {
445 fn new(inner: A) -> PanicPayload<A> {
446 PanicPayload { inner: Some(inner) }
447 }
448 }
449
450 unsafe impl<A: Send + 'static> BoxMeUp for PanicPayload<A> {
60c5eb7d 451 fn take_box(&mut self) -> *mut (dyn Any + Send) {
dfeec247
XL
452 // Note that this should be the only allocation performed in this code path. Currently
453 // this means that panic!() on OOM will invoke this code path, but then again we're not
454 // really ready for panic on OOM anyway. If we do start doing this, then we should
455 // propagate this allocation to be performed in the parent of this thread instead of the
456 // thread that's panicking.
83c7162d 457 let data = match self.inner.take() {
8faf50e0 458 Some(a) => Box::new(a) as Box<dyn Any + Send>,
60c5eb7d 459 None => process::abort(),
83c7162d
XL
460 };
461 Box::into_raw(data)
462 }
463
8faf50e0 464 fn get(&mut self) -> &(dyn Any + Send) {
83c7162d
XL
465 match self.inner {
466 Some(ref a) => a,
60c5eb7d 467 None => process::abort(),
83c7162d
XL
468 }
469 }
470 }
a7813a04
XL
471}
472
83c7162d 473/// Central point for dispatching panics.
a7813a04 474///
83c7162d
XL
475/// Executes the primary logic for a panic, including checking for recursive
476/// panics, panic hooks, and finally dispatching to the panic runtime to either
477/// abort or unwind.
dfeec247
XL
478fn rust_panic_with_hook(
479 payload: &mut dyn BoxMeUp,
480 message: Option<&fmt::Arguments<'_>>,
481 location: &Location<'_>,
482) -> ! {
5bcae85e 483 let panics = update_panic_count(1);
a7813a04 484
0731742a 485 // If this is the third nested call (e.g., panics == 2, this is 0-indexed),
a7813a04
XL
486 // the panic hook probably triggered the last panic, otherwise the
487 // double-panic check would have aborted the process. In this case abort the
488 // process real quickly as we don't want to try calling it again as it'll
489 // probably just panic again.
5bcae85e 490 if panics > 2 {
dfeec247
XL
491 util::dumb_print(format_args!(
492 "thread panicked while processing \
493 panic. aborting.\n"
494 ));
b039eaaf
SL
495 unsafe { intrinsics::abort() }
496 }
497
9cc50fc6 498 unsafe {
dfeec247 499 let mut info = PanicInfo::internal_constructor(message, location);
a7813a04 500 HOOK_LOCK.read();
54a0048b 501 match HOOK {
60c5eb7d 502 // Some platforms (like wasm) know that printing to stderr won't ever actually
83c7162d 503 // print anything, and if that's the case we can skip the default
60c5eb7d
XL
504 // hook. Since string formatting happens lazily when calling `payload`
505 // methods, this means we avoid formatting the string at all!
506 // (The panic runtime might still call `payload.take_box()` though and trigger
507 // formatting.)
0731742a 508 Hook::Default if panic_output().is_none() => {}
83c7162d
XL
509 Hook::Default => {
510 info.set_payload(payload.get());
511 default_hook(&info);
512 }
513 Hook::Custom(ptr) => {
514 info.set_payload(payload.get());
515 (*ptr)(&info);
516 }
0731742a 517 };
a7813a04 518 HOOK_LOCK.read_unlock();
9cc50fc6 519 }
b039eaaf 520
5bcae85e 521 if panics > 1 {
b039eaaf
SL
522 // If a thread panics while it's already unwinding then we
523 // have limited options. Currently our preference is to
524 // just abort. In the future we may consider resuming
525 // unwinding or otherwise exiting the thread cleanly.
dfeec247
XL
526 util::dumb_print(format_args!(
527 "thread panicked while panicking. \
528 aborting.\n"
529 ));
b039eaaf 530 unsafe { intrinsics::abort() }
1a4d82fc 531 }
a7813a04 532
0531ce1d 533 rust_panic(payload)
a7813a04
XL
534}
535
60c5eb7d
XL
536/// This is the entry point for `resume_unwind`.
537/// It just forwards the payload to the panic runtime.
538pub fn rust_panic_without_hook(payload: Box<dyn Any + Send>) -> ! {
5bcae85e 539 update_panic_count(1);
83c7162d 540
8faf50e0 541 struct RewrapBox(Box<dyn Any + Send>);
83c7162d
XL
542
543 unsafe impl BoxMeUp for RewrapBox {
60c5eb7d 544 fn take_box(&mut self) -> *mut (dyn Any + Send) {
83c7162d
XL
545 Box::into_raw(mem::replace(&mut self.0, Box::new(())))
546 }
547
8faf50e0 548 fn get(&mut self) -> &(dyn Any + Send) {
83c7162d
XL
549 &*self.0
550 }
551 }
552
60c5eb7d 553 rust_panic(&mut RewrapBox(payload))
5bcae85e
SL
554}
555
0bf4aa26
XL
556/// An unmangled function (through `rustc_std_internal_symbol`) on which to slap
557/// yer breakpoints.
558#[inline(never)]
559#[cfg_attr(not(test), rustc_std_internal_symbol)]
560fn rust_panic(mut msg: &mut dyn BoxMeUp) -> ! {
a7813a04 561 let code = unsafe {
8faf50e0 562 let obj = &mut msg as *mut &mut dyn BoxMeUp;
83c7162d 563 __rust_start_panic(obj as usize)
a7813a04
XL
564 };
565 rtabort!("failed to initiate panic, error {}", code)
1a4d82fc 566}