@@ -3,7 +3,7 @@ use std::mem;
33use either:: { Left , Right } ;
44
55use rustc_hir:: def:: DefKind ;
6- use rustc_middle:: mir:: interpret:: { ErrorHandled , InterpErrorInfo } ;
6+ use rustc_middle:: mir:: interpret:: { AllocId , ErrorHandled , InterpErrorInfo } ;
77use rustc_middle:: mir:: pretty:: write_allocation_bytes;
88use rustc_middle:: mir:: { self , ConstAlloc , ConstValue } ;
99use rustc_middle:: traits:: Reveal ;
@@ -285,15 +285,22 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
285285 let def = cid. instance . def . def_id ( ) ;
286286 let is_static = tcx. is_static ( def) ;
287287
288- let mut ecx = InterpCx :: new (
288+ let ecx = InterpCx :: new (
289289 tcx,
290290 tcx. def_span ( def) ,
291291 key. param_env ,
292292 // Statics (and promoteds inside statics) may access other statics, because unlike consts
293293 // they do not have to behave "as if" they were evaluated at runtime.
294294 CompileTimeInterpreter :: new ( CanAccessStatics :: from ( is_static) , CheckAlignment :: Error ) ,
295295 ) ;
296+ eval_in_interpreter ( ecx, cid, is_static)
297+ }
296298
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 > {
297304 let res = ecx. load_mir ( cid. instance . def , cid. promoted ) ;
298305 match res. and_then ( |body| eval_body_using_ecx ( & mut ecx, cid, & body) ) {
299306 Err ( error) => {
@@ -306,7 +313,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
306313 // If the current item has generics, we'd like to enrich the message with the
307314 // instance and its args: to show the actual compile-time values, in addition to
308315 // the expression, leading to the const eval error.
309- let instance = & key . value . instance ;
316+ let instance = & cid . instance ;
310317 if !instance. args . is_empty ( ) {
311318 let instance = with_no_trimmed_paths ! ( instance. to_string( ) ) ;
312319 ( "const_with_path" , instance)
@@ -331,60 +338,76 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
331338 Ok ( mplace) => {
332339 // Since evaluation had no errors, validate the resulting constant.
333340 // 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+
350344 let alloc_id = mplace. ptr ( ) . provenance . unwrap ( ) ;
351345
352346 // Validation failed, report an error.
353347 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) )
384349 } else {
385350 // Convert to raw constant
386351 Ok ( ConstAlloc { alloc_id, ty : mplace. layout . ty } )
387352 }
388353 }
389354 }
390355}
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