@@ -13,7 +13,7 @@ use crate::mir::eval::{
1313 name, pad16, static_lifetime, Address , AdtId , Arc , BuiltinType , Evaluator , FunctionId ,
1414 HasModule , HirDisplay , Interned , InternedClosure , Interner , Interval , IntervalAndTy ,
1515 IntervalOrOwned , ItemContainerId , LangItem , Layout , Locals , Lookup , MirEvalError , MirSpan ,
16- ModPath , Mutability , Result , Substitution , Ty , TyBuilder , TyExt ,
16+ Mutability , Result , Substitution , Ty , TyBuilder , TyExt ,
1717} ;
1818
1919mod simd;
@@ -158,6 +158,25 @@ impl Evaluator<'_> {
158158 Ok ( false )
159159 }
160160
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+
161180 /// Clone has special impls for tuples and function pointers
162181 fn exec_clone (
163182 & mut self ,
@@ -291,9 +310,14 @@ impl Evaluator<'_> {
291310 use LangItem :: * ;
292311 let candidate = self . db . lang_attr ( def. into ( ) ) ?;
293312 // 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) {
295315 return Some ( candidate) ;
296316 }
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+ }
297321 None
298322 }
299323
@@ -309,43 +333,6 @@ impl Evaluator<'_> {
309333 let mut args = args. iter ( ) ;
310334 match it {
311335 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- }
349336 SliceLen => {
350337 let arg = args. next ( ) . ok_or ( MirEvalError :: InternalError (
351338 "argument of <[T]>::len() is not provided" . into ( ) ,
0 commit comments