@@ -49,6 +49,7 @@ impl Evaluator<'_> {
49
49
if self . not_special_fn_cache . borrow ( ) . contains ( & def) {
50
50
return Ok ( false ) ;
51
51
}
52
+
52
53
let function_data = self . db . function_data ( def) ;
53
54
let is_intrinsic = match & function_data. abi {
54
55
Some ( abi) => * abi == Interned :: new_str ( "rust-intrinsic" ) ,
@@ -131,9 +132,7 @@ impl Evaluator<'_> {
131
132
return Ok ( true ) ;
132
133
}
133
134
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) ?;
137
136
destination. write_from_bytes ( self , & result) ?;
138
137
return Ok ( true ) ;
139
138
}
@@ -311,35 +310,73 @@ impl Evaluator<'_> {
311
310
312
311
fn detect_lang_function ( & self , def : FunctionId ) -> Option < LangItem > {
313
312
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) ?;
315
321
// We want to execute these functions with special logic
316
322
// `PanicFmt` is not detected here as it's redirected later.
317
323
if [ BeginPanic , SliceLen , DropInPlace ] . contains ( & candidate) {
318
324
return Some ( candidate) ;
319
325
}
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
+
324
327
None
325
328
}
326
329
327
330
fn exec_lang_item (
328
331
& mut self ,
329
332
it : LangItem ,
330
333
generic_args : & Substitution ,
331
- args : & [ Vec < u8 > ] ,
334
+ args : & [ IntervalAndTy ] ,
332
335
locals : & Locals ,
333
336
span : MirSpan ,
334
337
) -> Result < Vec < u8 > > {
335
338
use LangItem :: * ;
336
339
let mut args = args. iter ( ) ;
337
340
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
+ }
339
375
SliceLen => {
340
376
let arg = args. next ( ) . ok_or ( MirEvalError :: InternalError (
341
377
"argument of <[T]>::len() is not provided" . into ( ) ,
342
378
) ) ?;
379
+ let arg = arg. get ( self ) ?;
343
380
let ptr_size = arg. len ( ) / 2 ;
344
381
Ok ( arg[ ptr_size..] . into ( ) )
345
382
}
@@ -353,6 +390,7 @@ impl Evaluator<'_> {
353
390
let arg = args. next ( ) . ok_or ( MirEvalError :: InternalError (
354
391
"argument of drop_in_place is not provided" . into ( ) ,
355
392
) ) ?;
393
+ let arg = arg. interval . get ( self ) ?. to_owned ( ) ;
356
394
self . run_drop_glue_deep (
357
395
ty. clone ( ) ,
358
396
locals,
0 commit comments