@@ -49,6 +49,7 @@ impl Evaluator<'_> {
4949 if self . not_special_fn_cache . borrow ( ) . contains ( & def) {
5050 return Ok ( false ) ;
5151 }
52+
5253 let function_data = self . db . function_data ( def) ;
5354 let is_intrinsic = match & function_data. abi {
5455 Some ( abi) => * abi == Interned :: new_str ( "rust-intrinsic" ) ,
@@ -131,9 +132,7 @@ impl Evaluator<'_> {
131132 return Ok ( true ) ;
132133 }
133134 if let Some ( it) = self . detect_lang_function ( def) {
134- let arg_bytes =
135- args. iter ( ) . map ( |it| Ok ( it. get ( self ) ?. to_owned ( ) ) ) . collect :: < Result < Vec < _ > > > ( ) ?;
136- let result = self . exec_lang_item ( it, generic_args, & arg_bytes, locals, span) ?;
135+ let result = self . exec_lang_item ( it, generic_args, args, locals, span) ?;
137136 destination. write_from_bytes ( self , & result) ?;
138137 return Ok ( true ) ;
139138 }
@@ -311,35 +310,73 @@ impl Evaluator<'_> {
311310
312311 fn detect_lang_function ( & self , def : FunctionId ) -> Option < LangItem > {
313312 use LangItem :: * ;
314- let candidate = self . db . lang_attr ( def. into ( ) ) ?;
313+ let attrs = self . db . attrs ( def. into ( ) ) ;
314+
315+ if attrs. by_key ( "rustc_const_panic_str" ) . exists ( ) {
316+ // `#[rustc_const_panic_str]` is treated like `lang = "begin_panic"` by rustc CTFE.
317+ return Some ( LangItem :: BeginPanic ) ;
318+ }
319+
320+ let candidate = attrs. by_key ( "lang" ) . string_value ( ) . and_then ( LangItem :: from_str) ?;
315321 // We want to execute these functions with special logic
316322 // `PanicFmt` is not detected here as it's redirected later.
317323 if [ BeginPanic , SliceLen , DropInPlace ] . contains ( & candidate) {
318324 return Some ( candidate) ;
319325 }
320- if self . db . attrs ( def. into ( ) ) . by_key ( "rustc_const_panic_str" ) . exists ( ) {
321- // `#[rustc_const_panic_str]` is treated like `lang = "begin_panic"` by rustc CTFE.
322- return Some ( LangItem :: BeginPanic ) ;
323- }
326+
324327 None
325328 }
326329
327330 fn exec_lang_item (
328331 & mut self ,
329332 it : LangItem ,
330333 generic_args : & Substitution ,
331- args : & [ Vec < u8 > ] ,
334+ args : & [ IntervalAndTy ] ,
332335 locals : & Locals ,
333336 span : MirSpan ,
334337 ) -> Result < Vec < u8 > > {
335338 use LangItem :: * ;
336339 let mut args = args. iter ( ) ;
337340 match it {
338- BeginPanic => Err ( MirEvalError :: Panic ( "<unknown-panic-payload>" . to_owned ( ) ) ) ,
341+ BeginPanic => {
342+ let mut arg = args
343+ . next ( )
344+ . ok_or ( MirEvalError :: InternalError (
345+ "argument of BeginPanic is not provided" . into ( ) ,
346+ ) ) ?
347+ . clone ( ) ;
348+ while let TyKind :: Ref ( _, _, ty) = arg. ty . kind ( Interner ) {
349+ if ty. is_str ( ) {
350+ let ( pointee, metadata) = arg. interval . get ( self ) ?. split_at ( self . ptr_size ( ) ) ;
351+ let len = from_bytes ! ( usize , metadata) ;
352+
353+ return {
354+ Err ( MirEvalError :: Panic (
355+ std:: str:: from_utf8 (
356+ self . read_memory ( Address :: from_bytes ( pointee) ?, len) ?,
357+ )
358+ . unwrap ( )
359+ . to_owned ( ) ,
360+ ) )
361+ } ;
362+ }
363+ let size = self . size_of_sized ( & ty, locals, "begin panic arg" ) ?;
364+ let pointee = arg. interval . get ( self ) ?;
365+ arg = IntervalAndTy {
366+ interval : Interval :: new ( Address :: from_bytes ( pointee) ?, size) ,
367+ ty : ty. clone ( ) ,
368+ } ;
369+ }
370+ Err ( MirEvalError :: Panic ( format ! (
371+ "unknown-panic-payload: {:?}" ,
372+ arg. ty. kind( Interner )
373+ ) ) )
374+ }
339375 SliceLen => {
340376 let arg = args. next ( ) . ok_or ( MirEvalError :: InternalError (
341377 "argument of <[T]>::len() is not provided" . into ( ) ,
342378 ) ) ?;
379+ let arg = arg. get ( self ) ?;
343380 let ptr_size = arg. len ( ) / 2 ;
344381 Ok ( arg[ ptr_size..] . into ( ) )
345382 }
@@ -353,6 +390,7 @@ impl Evaluator<'_> {
353390 let arg = args. next ( ) . ok_or ( MirEvalError :: InternalError (
354391 "argument of drop_in_place is not provided" . into ( ) ,
355392 ) ) ?;
393+ let arg = arg. interval . get ( self ) ?. to_owned ( ) ;
356394 self . run_drop_glue_deep (
357395 ty. clone ( ) ,
358396 locals,
0 commit comments