Auto merge of #102732 - RalfJung:assert_unsafe_precondition2, r=bjorn3 · rust-lang/rust@538f118 (original) (raw)
`@@ -29,6 +29,73 @@
`
29
29
`use crate::fmt;
`
30
30
`use crate::panic::{Location, PanicInfo};
`
31
31
``
``
32
`+
// First we define the two main entry points that all panics go through.
`
``
33
`` +
// In the end both are just convenience wrappers around panic_impl
.
``
``
34
+
``
35
`+
/// The entry point for panicking with a formatted message.
`
``
36
`+
///
`
``
37
`+
/// This is designed to reduce the amount of code required at the call
`
``
38
`` +
/// site as much as possible (so that panic!()
has as low an impact
``
``
39
`+
/// on (e.g.) the inlining of other functions as possible), by moving
`
``
40
`+
/// the actual formatting into this shared place.
`
``
41
`+
#[cold]
`
``
42
`+
// If panic_immediate_abort, inline the abort call,
`
``
43
`+
// otherwise avoid inlining because of it is cold path.
`
``
44
`+
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
`
``
45
`+
#[cfg_attr(feature = "panic_immediate_abort", inline)]
`
``
46
`+
#[track_caller]
`
``
47
`+
#[lang = "panic_fmt"] // needed for const-evaluated panics
`
``
48
`+
#[rustc_do_not_const_check] // hooked by const-eval
`
``
49
`+
#[rustc_const_unstable(feature = "core_panic", issue = "none")]
`
``
50
`+
pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
`
``
51
`+
if cfg!(feature = "panic_immediate_abort") {
`
``
52
`+
super::intrinsics::abort()
`
``
53
`+
}
`
``
54
+
``
55
`+
// NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
`
``
56
`` +
// that gets resolved to the #[panic_handler]
function.
``
``
57
`+
extern "Rust" {
`
``
58
`+
#[lang = "panic_impl"]
`
``
59
`+
fn panic_impl(pi: &PanicInfo<'_>) -> !;
`
``
60
`+
}
`
``
61
+
``
62
`+
let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), true);
`
``
63
+
``
64
`` +
// SAFETY: panic_impl
is defined in safe Rust code and thus is safe to call.
``
``
65
`+
unsafe { panic_impl(&pi) }
`
``
66
`+
}
`
``
67
+
``
68
`+
/// Like panic_fmt, but without unwinding and track_caller to reduce the impact on codesize.
`
``
69
`` +
/// Also just works on str
, as a fmt::Arguments
needs more space to be passed.
``
``
70
`+
#[cold]
`
``
71
`+
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
`
``
72
`+
#[cfg_attr(feature = "panic_immediate_abort", inline)]
`
``
73
`+
#[cfg_attr(not(bootstrap), rustc_nounwind)]
`
``
74
`+
#[cfg_attr(bootstrap, rustc_allocator_nounwind)]
`
``
75
`+
pub fn panic_str_nounwind(msg: &'static str) -> ! {
`
``
76
`+
if cfg!(feature = "panic_immediate_abort") {
`
``
77
`+
super::intrinsics::abort()
`
``
78
`+
}
`
``
79
+
``
80
`+
// NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
`
``
81
`` +
// that gets resolved to the #[panic_handler]
function.
``
``
82
`+
extern "Rust" {
`
``
83
`+
#[lang = "panic_impl"]
`
``
84
`+
fn panic_impl(pi: &PanicInfo<'_>) -> !;
`
``
85
`+
}
`
``
86
+
``
87
`` +
// PanicInfo with the can_unwind
flag set to false forces an abort.
``
``
88
`+
let pieces = [msg];
`
``
89
`+
let fmt = fmt::Arguments::new_v1(&pieces, &[]);
`
``
90
`+
let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false);
`
``
91
+
``
92
`` +
// SAFETY: panic_impl
is defined in safe Rust code and thus is safe to call.
``
``
93
`+
unsafe { panic_impl(&pi) }
`
``
94
`+
}
`
``
95
+
``
96
`+
// Next we define a bunch of higher-level wrappers that all bottom out in the two core functions
`
``
97
`+
// above.
`
``
98
+
32
99
`` /// The underlying implementation of libcore's panic!
macro when no formatting is used.
``
33
100
`#[cold]
`
34
101
`// never inline unless panic_immediate_abort to avoid code
`
`@@ -84,62 +151,17 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
`
84
151
`panic!("index out of bounds: the len is {len} but the index is {index}")
`
85
152
`}
`
86
153
``
87
``
`-
// This function is called directly by the codegen backend, and must not have
`
88
``
`-
// any extra arguments (including those synthesized by track_caller).
`
``
154
`+
/// Panic because we cannot unwind out of a function.
`
``
155
`+
///
`
``
156
`+
/// This function is called directly by the codegen backend, and must not have
`
``
157
`+
/// any extra arguments (including those synthesized by track_caller).
`
89
158
`#[cold]
`
90
159
`#[inline(never)]
`
91
160
`#[lang = "panic_no_unwind"] // needed by codegen for panic in nounwind function
`
``
161
`+
#[cfg_attr(not(bootstrap), rustc_nounwind)]
`
``
162
`+
#[cfg_attr(bootstrap, rustc_allocator_nounwind)]
`
92
163
`fn panic_no_unwind() -> ! {
`
93
``
`-
if cfg!(feature = "panic_immediate_abort") {
`
94
``
`-
super::intrinsics::abort()
`
95
``
`-
}
`
96
``
-
97
``
`-
// NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
`
98
``
`` -
// that gets resolved to the #[panic_handler]
function.
``
99
``
`-
extern "Rust" {
`
100
``
`-
#[lang = "panic_impl"]
`
101
``
`-
fn panic_impl(pi: &PanicInfo<'_>) -> !;
`
102
``
`-
}
`
103
``
-
104
``
`` -
// PanicInfo with the can_unwind
flag set to false forces an abort.
``
105
``
`-
let fmt = format_args!("panic in a function that cannot unwind");
`
106
``
`-
let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false);
`
107
``
-
108
``
`` -
// SAFETY: panic_impl
is defined in safe Rust code and thus is safe to call.
``
109
``
`-
unsafe { panic_impl(&pi) }
`
110
``
`-
}
`
111
``
-
112
``
`-
/// The entry point for panicking with a formatted message.
`
113
``
`-
///
`
114
``
`-
/// This is designed to reduce the amount of code required at the call
`
115
``
`` -
/// site as much as possible (so that panic!()
has as low an impact
``
116
``
`-
/// on (e.g.) the inlining of other functions as possible), by moving
`
117
``
`-
/// the actual formatting into this shared place.
`
118
``
`-
#[cold]
`
119
``
`-
// If panic_immediate_abort, inline the abort call,
`
120
``
`-
// otherwise avoid inlining because of it is cold path.
`
121
``
`-
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
`
122
``
`-
#[cfg_attr(feature = "panic_immediate_abort", inline)]
`
123
``
`-
#[track_caller]
`
124
``
`-
#[lang = "panic_fmt"] // needed for const-evaluated panics
`
125
``
`-
#[rustc_do_not_const_check] // hooked by const-eval
`
126
``
`-
#[rustc_const_unstable(feature = "core_panic", issue = "none")]
`
127
``
`-
pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
`
128
``
`-
if cfg!(feature = "panic_immediate_abort") {
`
129
``
`-
super::intrinsics::abort()
`
130
``
`-
}
`
131
``
-
132
``
`-
// NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
`
133
``
`` -
// that gets resolved to the #[panic_handler]
function.
``
134
``
`-
extern "Rust" {
`
135
``
`-
#[lang = "panic_impl"]
`
136
``
`-
fn panic_impl(pi: &PanicInfo<'_>) -> !;
`
137
``
`-
}
`
138
``
-
139
``
`-
let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), true);
`
140
``
-
141
``
`` -
// SAFETY: panic_impl
is defined in safe Rust code and thus is safe to call.
``
142
``
`-
unsafe { panic_impl(&pi) }
`
``
164
`+
panic_str_nounwind("panic in a function that cannot unwind")
`
143
165
`}
`
144
166
``
145
167
`/// This function is used instead of panic_fmt in const eval.
`