@@ -130,17 +130,80 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo
130
130
#[ cfg_attr( feature = "panic_immediate_abort" , inline) ]
131
131
#[ track_caller]
132
132
#[ rustc_const_unstable( feature = "panic_internals" , issue = "none" ) ]
133
- #[ lang = "panic" ] // needed by codegen for panic on overflow and other `Assert` MIR terminators
133
+ #[ lang = "panic" ] // used by lints and miri for panics
134
134
pub const fn panic ( expr : & ' static str ) -> ! {
135
- // Use Arguments::new_v1 instead of format_args!("{expr}") to potentially
135
+ // Use Arguments::new_const instead of format_args!("{expr}") to potentially
136
136
// reduce size overhead. The format_args! macro uses str's Display trait to
137
137
// write expr, which calls Formatter::pad, which must accommodate string
138
138
// truncation and padding (even though none is used here). Using
139
- // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
139
+ // Arguments::new_const may allow the compiler to omit Formatter::pad from the
140
140
// output binary, saving up to a few kilobytes.
141
141
panic_fmt ( fmt:: Arguments :: new_const ( & [ expr] ) ) ;
142
142
}
143
143
144
+ // We generate functions for usage by compiler-generated assertions.
145
+ //
146
+ // Placing these functions in libcore means that all Rust programs can generate a jump into this
147
+ // code rather than expanding to panic("...") above, which adds extra bloat to call sites (for the
148
+ // constant string argument's pointer and length).
149
+ //
150
+ // This is especially important when this code is called often (e.g., with -Coverflow-checks) for
151
+ // reducing binary size impact.
152
+ macro_rules! panic_const {
153
+ ( $( $lang: ident = $message: expr, ) +) => {
154
+ #[ cfg( not( bootstrap) ) ]
155
+ pub mod panic_const {
156
+ use super :: * ;
157
+
158
+ $(
159
+ /// This is a panic called with a message that's a result of a MIR-produced Assert.
160
+ //
161
+ // never inline unless panic_immediate_abort to avoid code
162
+ // bloat at the call sites as much as possible
163
+ #[ cfg_attr( not( feature = "panic_immediate_abort" ) , inline( never) , cold) ]
164
+ #[ cfg_attr( feature = "panic_immediate_abort" , inline) ]
165
+ #[ track_caller]
166
+ #[ rustc_const_unstable( feature = "panic_internals" , issue = "none" ) ]
167
+ #[ lang = stringify!( $lang) ]
168
+ pub const fn $lang( ) -> ! {
169
+ // Use Arguments::new_const instead of format_args!("{expr}") to potentially
170
+ // reduce size overhead. The format_args! macro uses str's Display trait to
171
+ // write expr, which calls Formatter::pad, which must accommodate string
172
+ // truncation and padding (even though none is used here). Using
173
+ // Arguments::new_const may allow the compiler to omit Formatter::pad from the
174
+ // output binary, saving up to a few kilobytes.
175
+ panic_fmt( fmt:: Arguments :: new_const( & [ $message] ) ) ;
176
+ }
177
+ ) +
178
+ }
179
+ }
180
+ }
181
+
182
+ // Unfortunately this set of strings is replicated here and in a few places in the compiler in
183
+ // slightly different forms. It's not clear if there's a good way to deduplicate without adding
184
+ // special cases to the compiler (e.g., a const generic function wouldn't have a single definition
185
+ // shared across crates, which is exactly what we want here).
186
+ panic_const ! {
187
+ panic_const_add_overflow = "attempt to add with overflow" ,
188
+ panic_const_sub_overflow = "attempt to subtract with overflow" ,
189
+ panic_const_mul_overflow = "attempt to multiply with overflow" ,
190
+ panic_const_div_overflow = "attempt to divide with overflow" ,
191
+ panic_const_rem_overflow = "attempt to calculate the remainder with overflow" ,
192
+ panic_const_neg_overflow = "attempt to negate with overflow" ,
193
+ panic_const_shr_overflow = "attempt to shift right with overflow" ,
194
+ panic_const_shl_overflow = "attempt to shift left with overflow" ,
195
+ panic_const_div_by_zero = "attempt to divide by zero" ,
196
+ panic_const_rem_by_zero = "attempt to calculate the remainder with a divisor of zero" ,
197
+ panic_const_coroutine_resumed = "coroutine resumed after completion" ,
198
+ panic_const_async_fn_resumed = "`async fn` resumed after completion" ,
199
+ panic_const_async_gen_fn_resumed = "`async gen fn` resumed after completion" ,
200
+ panic_const_gen_fn_none = "`gen fn` should just keep returning `None` after completion" ,
201
+ panic_const_coroutine_resumed_panic = "coroutine resumed after panicking" ,
202
+ panic_const_async_fn_resumed_panic = "`async fn` resumed after panicking" ,
203
+ panic_const_async_gen_fn_resumed_panic = "`async gen fn` resumed after panicking" ,
204
+ panic_const_gen_fn_none_panic = "`gen fn` should just keep returning `None` after panicking" ,
205
+ }
206
+
144
207
/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize on the caller.
145
208
/// If you want `#[track_caller]` for nicer errors, call `panic_nounwind_fmt` directly.
146
209
#[ cfg_attr( not( feature = "panic_immediate_abort" ) , inline( never) , cold) ]
0 commit comments