@@ -45,9 +45,15 @@ fn mk_eval_cx<'mir, 'tcx>(
4545 tcx : TyCtxt < ' tcx > ,
4646 span : Span ,
4747 param_env : ty:: ParamEnv < ' tcx > ,
48+ can_access_statics : bool ,
4849) -> CompileTimeEvalContext < ' mir , ' tcx > {
4950 debug ! ( "mk_eval_cx: {:?}" , param_env) ;
50- InterpCx :: new ( tcx. at ( span) , param_env, CompileTimeInterpreter :: new ( ) , Default :: default ( ) )
51+ InterpCx :: new (
52+ tcx. at ( span) ,
53+ param_env,
54+ CompileTimeInterpreter :: new ( ) ,
55+ MemoryExtra { can_access_statics } ,
56+ )
5157}
5258
5359fn op_to_const < ' tcx > (
@@ -176,6 +182,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
176182#[ derive( Clone , Debug ) ]
177183pub enum ConstEvalError {
178184 NeedsRfc ( String ) ,
185+ ConstAccessesStatic ,
179186}
180187
181188impl < ' tcx > Into < InterpErrorInfo < ' tcx > > for ConstEvalError {
@@ -195,6 +202,7 @@ impl fmt::Display for ConstEvalError {
195202 msg
196203 )
197204 }
205+ ConstAccessesStatic => write ! ( f, "constant accesses static" ) ,
198206 }
199207 }
200208}
@@ -204,6 +212,7 @@ impl Error for ConstEvalError {
204212 use self :: ConstEvalError :: * ;
205213 match * self {
206214 NeedsRfc ( _) => "this feature needs an rfc before being allowed inside constants" ,
215+ ConstAccessesStatic => "constant accesses static" ,
207216 }
208217 }
209218
@@ -224,6 +233,12 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
224233 pub ( super ) loop_detector : snapshot:: InfiniteLoopDetector < ' mir , ' tcx > ,
225234}
226235
236+ #[ derive( Copy , Clone , Debug ) ]
237+ pub struct MemoryExtra {
238+ /// Whether this machine may read from statics
239+ can_access_statics : bool ,
240+ }
241+
227242impl < ' mir , ' tcx > CompileTimeInterpreter < ' mir , ' tcx > {
228243 fn new ( ) -> Self {
229244 CompileTimeInterpreter {
@@ -311,7 +326,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
311326 type ExtraFnVal = !;
312327
313328 type FrameExtra = ( ) ;
314- type MemoryExtra = ( ) ;
329+ type MemoryExtra = MemoryExtra ;
315330 type AllocExtra = ( ) ;
316331
317332 type MemoryMap = FxHashMap < AllocId , ( MemoryKind < !> , Allocation ) > ;
@@ -473,7 +488,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
473488
474489 #[ inline( always) ]
475490 fn init_allocation_extra < ' b > (
476- _memory_extra : & ( ) ,
491+ _memory_extra : & MemoryExtra ,
477492 _id : AllocId ,
478493 alloc : Cow < ' b , Allocation > ,
479494 _kind : Option < MemoryKind < !> > ,
@@ -484,7 +499,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
484499
485500 #[ inline( always) ]
486501 fn tag_static_base_pointer (
487- _memory_extra : & ( ) ,
502+ _memory_extra : & MemoryExtra ,
488503 _id : AllocId ,
489504 ) -> Self :: PointerTag {
490505 ( )
@@ -527,6 +542,17 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
527542 fn stack_push ( _ecx : & mut InterpCx < ' mir , ' tcx , Self > ) -> InterpResult < ' tcx > {
528543 Ok ( ( ) )
529544 }
545+
546+ fn before_access_static (
547+ memory_extra : & MemoryExtra ,
548+ _allocation : & Allocation ,
549+ ) -> InterpResult < ' tcx > {
550+ if memory_extra. can_access_statics {
551+ Ok ( ( ) )
552+ } else {
553+ Err ( ConstEvalError :: ConstAccessesStatic . into ( ) )
554+ }
555+ }
530556}
531557
532558/// Extracts a field of a (variant of a) const.
@@ -540,7 +566,7 @@ pub fn const_field<'tcx>(
540566 value : & ' tcx ty:: Const < ' tcx > ,
541567) -> & ' tcx ty:: Const < ' tcx > {
542568 trace ! ( "const_field: {:?}, {:?}" , field, value) ;
543- let ecx = mk_eval_cx ( tcx, DUMMY_SP , param_env) ;
569+ let ecx = mk_eval_cx ( tcx, DUMMY_SP , param_env, false ) ;
544570 // get the operand again
545571 let op = ecx. eval_const_to_op ( value, None ) . unwrap ( ) ;
546572 // downcast
@@ -560,7 +586,7 @@ pub fn const_caller_location<'tcx>(
560586 ( file, line, col) : ( Symbol , u32 , u32 ) ,
561587) -> & ' tcx ty:: Const < ' tcx > {
562588 trace ! ( "const_caller_location: {}:{}:{}" , file, line, col) ;
563- let mut ecx = mk_eval_cx ( tcx, DUMMY_SP , ty:: ParamEnv :: reveal_all ( ) ) ;
589+ let mut ecx = mk_eval_cx ( tcx, DUMMY_SP , ty:: ParamEnv :: reveal_all ( ) , false ) ;
564590
565591 let loc_ty = tcx. caller_location_ty ( ) ;
566592 let loc_place = ecx. alloc_caller_location ( file, line, col) ;
@@ -581,7 +607,7 @@ pub fn const_variant_index<'tcx>(
581607 val : & ' tcx ty:: Const < ' tcx > ,
582608) -> VariantIdx {
583609 trace ! ( "const_variant_index: {:?}" , val) ;
584- let ecx = mk_eval_cx ( tcx, DUMMY_SP , param_env) ;
610+ let ecx = mk_eval_cx ( tcx, DUMMY_SP , param_env, false ) ;
585611 let op = ecx. eval_const_to_op ( val, None ) . unwrap ( ) ;
586612 ecx. read_discriminant ( op) . unwrap ( ) . 1
587613}
@@ -610,7 +636,9 @@ fn validate_and_turn_into_const<'tcx>(
610636 key : ty:: ParamEnvAnd < ' tcx , GlobalId < ' tcx > > ,
611637) -> :: rustc:: mir:: interpret:: ConstEvalResult < ' tcx > {
612638 let cid = key. value ;
613- let ecx = mk_eval_cx ( tcx, tcx. def_span ( key. value . instance . def_id ( ) ) , key. param_env ) ;
639+ let def_id = cid. instance . def . def_id ( ) ;
640+ let is_static = tcx. is_static ( def_id) ;
641+ let ecx = mk_eval_cx ( tcx, tcx. def_span ( key. value . instance . def_id ( ) ) , key. param_env , is_static) ;
614642 let val = ( || {
615643 let mplace = ecx. raw_const_to_mplace ( constant) ?;
616644 let mut ref_tracking = RefTracking :: new ( mplace) ;
@@ -624,8 +652,7 @@ fn validate_and_turn_into_const<'tcx>(
624652 // Now that we validated, turn this into a proper constant.
625653 // Statics/promoteds are always `ByRef`, for the rest `op_to_const` decides
626654 // whether they become immediates.
627- let def_id = cid. instance . def . def_id ( ) ;
628- if tcx. is_static ( def_id) || cid. promoted . is_some ( ) {
655+ if is_static || cid. promoted . is_some ( ) {
629656 let ptr = mplace. ptr . to_ptr ( ) ?;
630657 Ok ( tcx. mk_const ( ty:: Const {
631658 val : ty:: ConstKind :: Value ( ConstValue :: ByRef {
@@ -732,12 +759,14 @@ pub fn const_eval_raw_provider<'tcx>(
732759 return Err ( ErrorHandled :: Reported ) ;
733760 }
734761
762+ let is_static = tcx. is_static ( def_id) ;
763+
735764 let span = tcx. def_span ( cid. instance . def_id ( ) ) ;
736765 let mut ecx = InterpCx :: new (
737766 tcx. at ( span) ,
738767 key. param_env ,
739768 CompileTimeInterpreter :: new ( ) ,
740- Default :: default ( )
769+ MemoryExtra { can_access_statics : is_static } ,
741770 ) ;
742771
743772 let res = ecx. load_mir ( cid. instance . def , cid. promoted ) ;
@@ -751,7 +780,7 @@ pub fn const_eval_raw_provider<'tcx>(
751780 } ) . map_err ( |error| {
752781 let err = error_to_const_error ( & ecx, error) ;
753782 // errors in statics are always emitted as fatal errors
754- if tcx . is_static ( def_id ) {
783+ if is_static {
755784 // Ensure that if the above error was either `TooGeneric` or `Reported`
756785 // an error must be reported.
757786 let v = err. report_as_error ( ecx. tcx , "could not evaluate static initializer" ) ;
0 commit comments