@@ -13,7 +13,7 @@ use crate::mir::eval::{
13
13
name, pad16, static_lifetime, Address , AdtId , Arc , BuiltinType , Evaluator , FunctionId ,
14
14
HasModule , HirDisplay , Interned , InternedClosure , Interner , Interval , IntervalAndTy ,
15
15
IntervalOrOwned , ItemContainerId , LangItem , Layout , Locals , Lookup , MirEvalError , MirSpan ,
16
- ModPath , Mutability , Result , Substitution , Ty , TyBuilder , TyExt ,
16
+ Mutability , Result , Substitution , Ty , TyBuilder , TyExt ,
17
17
} ;
18
18
19
19
mod simd;
@@ -158,6 +158,25 @@ impl Evaluator<'_> {
158
158
Ok ( false )
159
159
}
160
160
161
+ pub ( super ) fn detect_and_redirect_special_function (
162
+ & mut self ,
163
+ def : FunctionId ,
164
+ ) -> Result < Option < FunctionId > > {
165
+ // `PanicFmt` is redirected to `ConstPanicFmt`
166
+ if let Some ( LangItem :: PanicFmt ) = self . db . lang_attr ( def. into ( ) ) {
167
+ let resolver =
168
+ self . db . crate_def_map ( self . crate_id ) . crate_root ( ) . resolver ( self . db . upcast ( ) ) ;
169
+
170
+ let Some ( hir_def:: lang_item:: LangItemTarget :: Function ( const_panic_fmt) ) =
171
+ self . db . lang_item ( resolver. krate ( ) , LangItem :: ConstPanicFmt )
172
+ else {
173
+ not_supported ! ( "const_panic_fmt lang item not found or not a function" ) ;
174
+ } ;
175
+ return Ok ( Some ( const_panic_fmt) ) ;
176
+ }
177
+ Ok ( None )
178
+ }
179
+
161
180
/// Clone has special impls for tuples and function pointers
162
181
fn exec_clone (
163
182
& mut self ,
@@ -291,9 +310,14 @@ impl Evaluator<'_> {
291
310
use LangItem :: * ;
292
311
let candidate = self . db . lang_attr ( def. into ( ) ) ?;
293
312
// We want to execute these functions with special logic
294
- if [ PanicFmt , BeginPanic , SliceLen , DropInPlace ] . contains ( & candidate) {
313
+ // `PanicFmt` is not detected here as it's redirected later.
314
+ if [ BeginPanic , SliceLen , DropInPlace ] . contains ( & candidate) {
295
315
return Some ( candidate) ;
296
316
}
317
+ if self . db . attrs ( def. into ( ) ) . by_key ( "rustc_const_panic_str" ) . exists ( ) {
318
+ // `#[rustc_const_panic_str]` is treated like `lang = "begin_panic"` by rustc CTFE.
319
+ return Some ( LangItem :: BeginPanic ) ;
320
+ }
297
321
None
298
322
}
299
323
@@ -309,43 +333,6 @@ impl Evaluator<'_> {
309
333
let mut args = args. iter ( ) ;
310
334
match it {
311
335
BeginPanic => Err ( MirEvalError :: Panic ( "<unknown-panic-payload>" . to_owned ( ) ) ) ,
312
- PanicFmt => {
313
- let message = ( || {
314
- let resolver = self
315
- . db
316
- . crate_def_map ( self . crate_id )
317
- . crate_root ( )
318
- . resolver ( self . db . upcast ( ) ) ;
319
- let Some ( format_fn) = resolver. resolve_path_in_value_ns_fully (
320
- self . db . upcast ( ) ,
321
- & hir_def:: path:: Path :: from_known_path_with_no_generic (
322
- ModPath :: from_segments (
323
- hir_expand:: mod_path:: PathKind :: Abs ,
324
- [ name ! [ std] , name ! [ fmt] , name ! [ format] ] ,
325
- ) ,
326
- ) ,
327
- ) else {
328
- not_supported ! ( "std::fmt::format not found" ) ;
329
- } ;
330
- let hir_def:: resolver:: ValueNs :: FunctionId ( format_fn) = format_fn else {
331
- not_supported ! ( "std::fmt::format is not a function" )
332
- } ;
333
- let interval = self . interpret_mir (
334
- self . db
335
- . mir_body ( format_fn. into ( ) )
336
- . map_err ( |e| MirEvalError :: MirLowerError ( format_fn, e) ) ?,
337
- args. map ( |x| IntervalOrOwned :: Owned ( x. clone ( ) ) ) ,
338
- ) ?;
339
- let message_string = interval. get ( self ) ?;
340
- let addr =
341
- Address :: from_bytes ( & message_string[ self . ptr_size ( ) ..2 * self . ptr_size ( ) ] ) ?;
342
- let size = from_bytes ! ( usize , message_string[ 2 * self . ptr_size( ) ..] ) ;
343
- Ok ( std:: string:: String :: from_utf8_lossy ( self . read_memory ( addr, size) ?)
344
- . into_owned ( ) )
345
- } ) ( )
346
- . unwrap_or_else ( |e| format ! ( "Failed to render panic format args: {e:?}" ) ) ;
347
- Err ( MirEvalError :: Panic ( message) )
348
- }
349
336
SliceLen => {
350
337
let arg = args. next ( ) . ok_or ( MirEvalError :: InternalError (
351
338
"argument of <[T]>::len() is not provided" . into ( ) ,
0 commit comments