@@ -3,7 +3,7 @@ use std::mem;
3
3
use either:: { Left , Right } ;
4
4
5
5
use rustc_hir:: def:: DefKind ;
6
- use rustc_middle:: mir:: interpret:: { ErrorHandled , InterpErrorInfo } ;
6
+ use rustc_middle:: mir:: interpret:: { AllocId , ErrorHandled , InterpErrorInfo } ;
7
7
use rustc_middle:: mir:: pretty:: write_allocation_bytes;
8
8
use rustc_middle:: mir:: { self , ConstAlloc , ConstValue } ;
9
9
use rustc_middle:: traits:: Reveal ;
@@ -285,15 +285,22 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
285
285
let def = cid. instance . def . def_id ( ) ;
286
286
let is_static = tcx. is_static ( def) ;
287
287
288
- let mut ecx = InterpCx :: new (
288
+ let ecx = InterpCx :: new (
289
289
tcx,
290
290
tcx. def_span ( def) ,
291
291
key. param_env ,
292
292
// Statics (and promoteds inside statics) may access other statics, because unlike consts
293
293
// they do not have to behave "as if" they were evaluated at runtime.
294
294
CompileTimeInterpreter :: new ( CanAccessStatics :: from ( is_static) , CheckAlignment :: Error ) ,
295
295
) ;
296
+ eval_in_interpreter ( ecx, cid, is_static)
297
+ }
296
298
299
+ pub fn eval_in_interpreter < ' mir , ' tcx > (
300
+ mut ecx : InterpCx < ' mir , ' tcx , CompileTimeInterpreter < ' mir , ' tcx > > ,
301
+ cid : GlobalId < ' tcx > ,
302
+ is_static : bool ,
303
+ ) -> :: rustc_middle:: mir:: interpret:: EvalToAllocationRawResult < ' tcx > {
297
304
let res = ecx. load_mir ( cid. instance . def , cid. promoted ) ;
298
305
match res. and_then ( |body| eval_body_using_ecx ( & mut ecx, cid, & body) ) {
299
306
Err ( error) => {
@@ -306,7 +313,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
306
313
// If the current item has generics, we'd like to enrich the message with the
307
314
// instance and its args: to show the actual compile-time values, in addition to
308
315
// the expression, leading to the const eval error.
309
- let instance = & key . value . instance ;
316
+ let instance = & cid . instance ;
310
317
if !instance. args . is_empty ( ) {
311
318
let instance = with_no_trimmed_paths ! ( instance. to_string( ) ) ;
312
319
( "const_with_path" , instance)
@@ -331,60 +338,76 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
331
338
Ok ( mplace) => {
332
339
// Since evaluation had no errors, validate the resulting constant.
333
340
// This is a separate `try` block to provide more targeted error reporting.
334
- let validation: Result < _ , InterpErrorInfo < ' _ > > = try {
335
- let mut ref_tracking = RefTracking :: new ( mplace. clone ( ) ) ;
336
- let mut inner = false ;
337
- while let Some ( ( mplace, path) ) = ref_tracking. todo . pop ( ) {
338
- let mode = match tcx. static_mutability ( cid. instance . def_id ( ) ) {
339
- Some ( _) if cid. promoted . is_some ( ) => {
340
- // Promoteds in statics are allowed to point to statics.
341
- CtfeValidationMode :: Const { inner, allow_static_ptrs : true }
342
- }
343
- Some ( _) => CtfeValidationMode :: Regular , // a `static`
344
- None => CtfeValidationMode :: Const { inner, allow_static_ptrs : false } ,
345
- } ;
346
- ecx. const_validate_operand ( & mplace. into ( ) , path, & mut ref_tracking, mode) ?;
347
- inner = true ;
348
- }
349
- } ;
341
+ let validation =
342
+ const_validate_mplace ( & ecx, & mplace, is_static, cid. promoted . is_some ( ) ) ;
343
+
350
344
let alloc_id = mplace. ptr ( ) . provenance . unwrap ( ) ;
351
345
352
346
// Validation failed, report an error.
353
347
if let Err ( error) = validation {
354
- let ( error, backtrace) = error. into_parts ( ) ;
355
- backtrace. print_backtrace ( ) ;
356
-
357
- let ub_note = matches ! ( error, InterpError :: UndefinedBehavior ( _) ) . then ( || { } ) ;
358
-
359
- let alloc = ecx. tcx . global_alloc ( alloc_id) . unwrap_memory ( ) . inner ( ) ;
360
- let mut bytes = String :: new ( ) ;
361
- if alloc. size ( ) != abi:: Size :: ZERO {
362
- bytes = "\n " . into ( ) ;
363
- // FIXME(translation) there might be pieces that are translatable.
364
- write_allocation_bytes ( * ecx. tcx , alloc, & mut bytes, " " ) . unwrap ( ) ;
365
- }
366
- let raw_bytes = errors:: RawBytesNote {
367
- size : alloc. size ( ) . bytes ( ) ,
368
- align : alloc. align . bytes ( ) ,
369
- bytes,
370
- } ;
371
-
372
- Err ( super :: report (
373
- * ecx. tcx ,
374
- error,
375
- None ,
376
- || super :: get_span_and_frames ( & ecx) ,
377
- move |span, frames| errors:: UndefinedBehavior {
378
- span,
379
- ub_note,
380
- frames,
381
- raw_bytes,
382
- } ,
383
- ) )
348
+ Err ( const_report_error ( & ecx, error, alloc_id) )
384
349
} else {
385
350
// Convert to raw constant
386
351
Ok ( ConstAlloc { alloc_id, ty : mplace. layout . ty } )
387
352
}
388
353
}
389
354
}
390
355
}
356
+
357
+ #[ inline( always) ]
358
+ pub fn const_validate_mplace < ' mir , ' tcx > (
359
+ ecx : & InterpCx < ' mir , ' tcx , CompileTimeInterpreter < ' mir , ' tcx > > ,
360
+ mplace : & MPlaceTy < ' tcx > ,
361
+ is_static : bool ,
362
+ is_promoted : bool ,
363
+ ) -> InterpResult < ' tcx > {
364
+ let mut ref_tracking = RefTracking :: new ( mplace. clone ( ) ) ;
365
+ let mut inner = false ;
366
+ while let Some ( ( mplace, path) ) = ref_tracking. todo . pop ( ) {
367
+ let mode = if is_static {
368
+ if is_promoted {
369
+ // Promoteds in statics are allowed to point to statics.
370
+ CtfeValidationMode :: Const { inner, allow_static_ptrs : true }
371
+ } else {
372
+ // a `static`
373
+ CtfeValidationMode :: Regular
374
+ }
375
+ } else {
376
+ CtfeValidationMode :: Const { inner, allow_static_ptrs : false }
377
+ } ;
378
+ ecx. const_validate_operand ( & mplace. into ( ) , path, & mut ref_tracking, mode) ?;
379
+ inner = true ;
380
+ }
381
+
382
+ Ok ( ( ) )
383
+ }
384
+
385
+ #[ inline( always) ]
386
+ pub fn const_report_error < ' mir , ' tcx > (
387
+ ecx : & InterpCx < ' mir , ' tcx , CompileTimeInterpreter < ' mir , ' tcx > > ,
388
+ error : InterpErrorInfo < ' tcx > ,
389
+ alloc_id : AllocId ,
390
+ ) -> ErrorHandled {
391
+ let ( error, backtrace) = error. into_parts ( ) ;
392
+ backtrace. print_backtrace ( ) ;
393
+
394
+ let ub_note = matches ! ( error, InterpError :: UndefinedBehavior ( _) ) . then ( || { } ) ;
395
+
396
+ let alloc = ecx. tcx . global_alloc ( alloc_id) . unwrap_memory ( ) . inner ( ) ;
397
+ let mut bytes = String :: new ( ) ;
398
+ if alloc. size ( ) != abi:: Size :: ZERO {
399
+ bytes = "\n " . into ( ) ;
400
+ // FIXME(translation) there might be pieces that are translatable.
401
+ write_allocation_bytes ( * ecx. tcx , alloc, & mut bytes, " " ) . unwrap ( ) ;
402
+ }
403
+ let raw_bytes =
404
+ errors:: RawBytesNote { size : alloc. size ( ) . bytes ( ) , align : alloc. align . bytes ( ) , bytes } ;
405
+
406
+ crate :: const_eval:: report (
407
+ * ecx. tcx ,
408
+ error,
409
+ None ,
410
+ || crate :: const_eval:: get_span_and_frames ( ecx) ,
411
+ move |span, frames| errors:: UndefinedBehavior { span, ub_note, frames, raw_bytes } ,
412
+ )
413
+ }
0 commit comments