]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | //! Panic support for libcore |
2 | //! | |
3 | //! The core library cannot define panicking, but it does *declare* panicking. This | |
4 | //! means that the functions inside of libcore are allowed to panic, but to be | |
5 | //! useful an upstream crate must define panicking for libcore to use. The current | |
6 | //! interface for panicking is: | |
7 | //! | |
041b39d2 | 8 | //! ``` |
60c5eb7d | 9 | //! fn panic_impl(pi: &core::panic::PanicInfo<'_>) -> ! |
041b39d2 | 10 | //! # { loop {} } |
1a4d82fc JJ |
11 | //! ``` |
12 | //! | |
13 | //! This definition allows for panicking with any general message, but it does not | |
60c5eb7d XL |
14 | //! allow for failing with a `Box<Any>` value. (`PanicInfo` just contains a `&(dyn Any + Send)`, |
15 | //! for which we fill in a dummy value in `PanicInfo::internal_constructor`.) | |
16 | //! The reason for this is that libcore is not allowed to allocate. | |
1a4d82fc JJ |
17 | //! |
18 | //! This module contains a few other panicking functions, but these are just the | |
19 | //! necessary lang items for the compiler. All panics are funneled through this | |
60c5eb7d XL |
20 | //! one function. The actual symbol is declared through the `#[panic_handler]` attribute. |
21 | ||
22 | // ignore-tidy-undocumented-unsafe | |
1a4d82fc JJ |
23 | |
24 | #![allow(dead_code, missing_docs)] | |
60c5eb7d XL |
25 | #![unstable( |
26 | feature = "core_panic", | |
27 | reason = "internal details of the implementation of the `panic!` \ | |
28 | and related macros", | |
29 | issue = "0" | |
30 | )] | |
1a4d82fc | 31 | |
48663c56 XL |
32 | use crate::fmt; |
33 | use crate::panic::{Location, PanicInfo}; | |
1a4d82fc | 34 | |
a1dfa0c6 XL |
35 | #[cold] |
36 | // never inline unless panic_immediate_abort to avoid code | |
37 | // bloat at the call sites as much as possible | |
60c5eb7d XL |
38 | #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] |
39 | #[lang = "panic"] // needed by codegen for panic on overflow and other `Assert` MIR terminators | |
e74abb32 XL |
40 | pub fn panic(expr: &str, location: &Location<'_>) -> ! { |
41 | if cfg!(feature = "panic_immediate_abort") { | |
42 | unsafe { super::intrinsics::abort() } | |
43 | } | |
44 | ||
45 | // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially | |
46 | // reduce size overhead. The format_args! macro uses str's Display trait to | |
47 | // write expr, which calls Formatter::pad, which must accommodate string | |
48 | // truncation and padding (even though none is used here). Using | |
49 | // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the | |
50 | // output binary, saving up to a few kilobytes. | |
51 | panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), location) | |
52 | } | |
53 | ||
a1dfa0c6 | 54 | #[cold] |
60c5eb7d XL |
55 | #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] |
56 | #[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access | |
e74abb32 XL |
57 | fn panic_bounds_check(location: &Location<'_>, index: usize, len: usize) -> ! { |
58 | if cfg!(feature = "panic_immediate_abort") { | |
59 | unsafe { super::intrinsics::abort() } | |
60 | } | |
61 | ||
62 | panic_fmt( | |
63 | format_args!("index out of bounds: the len is {} but the index is {}", len, index), | |
60c5eb7d | 64 | location, |
e74abb32 XL |
65 | ) |
66 | } | |
67 | ||
e74abb32 | 68 | #[cold] |
60c5eb7d XL |
69 | #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] |
70 | #[cfg_attr(feature = "panic_immediate_abort", inline)] | |
e74abb32 XL |
71 | pub fn panic_fmt(fmt: fmt::Arguments<'_>, location: &Location<'_>) -> ! { |
72 | if cfg!(feature = "panic_immediate_abort") { | |
73 | unsafe { super::intrinsics::abort() } | |
74 | } | |
75 | ||
76 | // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call | |
60c5eb7d | 77 | // that gets resolved to the `#[panic_handler]` function. |
e74abb32 XL |
78 | extern "Rust" { |
79 | #[lang = "panic_impl"] | |
80 | fn panic_impl(pi: &PanicInfo<'_>) -> !; | |
81 | } | |
82 | ||
83 | let pi = PanicInfo::internal_constructor(Some(&fmt), location); | |
94b46f34 XL |
84 | unsafe { panic_impl(&pi) } |
85 | } |