@@ -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