@@ -45,9 +45,15 @@ fn mk_eval_cx<'mir, 'tcx>(
45
45
tcx : TyCtxt < ' tcx > ,
46
46
span : Span ,
47
47
param_env : ty:: ParamEnv < ' tcx > ,
48
+ can_access_statics : bool ,
48
49
) -> CompileTimeEvalContext < ' mir , ' tcx > {
49
50
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
+ )
51
57
}
52
58
53
59
fn op_to_const < ' tcx > (
@@ -176,6 +182,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
176
182
#[ derive( Clone , Debug ) ]
177
183
pub enum ConstEvalError {
178
184
NeedsRfc ( String ) ,
185
+ ConstAccessesStatic ,
179
186
}
180
187
181
188
impl < ' tcx > Into < InterpErrorInfo < ' tcx > > for ConstEvalError {
@@ -195,6 +202,7 @@ impl fmt::Display for ConstEvalError {
195
202
msg
196
203
)
197
204
}
205
+ ConstAccessesStatic => write ! ( f, "constant accesses static" ) ,
198
206
}
199
207
}
200
208
}
@@ -204,6 +212,7 @@ impl Error for ConstEvalError {
204
212
use self :: ConstEvalError :: * ;
205
213
match * self {
206
214
NeedsRfc ( _) => "this feature needs an rfc before being allowed inside constants" ,
215
+ ConstAccessesStatic => "constant accesses static" ,
207
216
}
208
217
}
209
218
@@ -224,6 +233,12 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
224
233
pub ( super ) loop_detector : snapshot:: InfiniteLoopDetector < ' mir , ' tcx > ,
225
234
}
226
235
236
+ #[ derive( Copy , Clone , Debug ) ]
237
+ pub struct MemoryExtra {
238
+ /// Whether this machine may read from statics
239
+ can_access_statics : bool ,
240
+ }
241
+
227
242
impl < ' mir , ' tcx > CompileTimeInterpreter < ' mir , ' tcx > {
228
243
fn new ( ) -> Self {
229
244
CompileTimeInterpreter {
@@ -311,7 +326,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
311
326
type ExtraFnVal = !;
312
327
313
328
type FrameExtra = ( ) ;
314
- type MemoryExtra = ( ) ;
329
+ type MemoryExtra = MemoryExtra ;
315
330
type AllocExtra = ( ) ;
316
331
317
332
type MemoryMap = FxHashMap < AllocId , ( MemoryKind < !> , Allocation ) > ;
@@ -473,7 +488,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
473
488
474
489
#[ inline( always) ]
475
490
fn init_allocation_extra < ' b > (
476
- _memory_extra : & ( ) ,
491
+ _memory_extra : & MemoryExtra ,
477
492
_id : AllocId ,
478
493
alloc : Cow < ' b , Allocation > ,
479
494
_kind : Option < MemoryKind < !> > ,
@@ -484,7 +499,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
484
499
485
500
#[ inline( always) ]
486
501
fn tag_static_base_pointer (
487
- _memory_extra : & ( ) ,
502
+ _memory_extra : & MemoryExtra ,
488
503
_id : AllocId ,
489
504
) -> Self :: PointerTag {
490
505
( )
@@ -527,6 +542,17 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
527
542
fn stack_push ( _ecx : & mut InterpCx < ' mir , ' tcx , Self > ) -> InterpResult < ' tcx > {
528
543
Ok ( ( ) )
529
544
}
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
+ }
530
556
}
531
557
532
558
/// Extracts a field of a (variant of a) const.
@@ -540,7 +566,7 @@ pub fn const_field<'tcx>(
540
566
value : & ' tcx ty:: Const < ' tcx > ,
541
567
) -> & ' tcx ty:: Const < ' tcx > {
542
568
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 ) ;
544
570
// get the operand again
545
571
let op = ecx. eval_const_to_op ( value, None ) . unwrap ( ) ;
546
572
// downcast
@@ -560,7 +586,7 @@ pub fn const_caller_location<'tcx>(
560
586
( file, line, col) : ( Symbol , u32 , u32 ) ,
561
587
) -> & ' tcx ty:: Const < ' tcx > {
562
588
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 ) ;
564
590
565
591
let loc_ty = tcx. caller_location_ty ( ) ;
566
592
let loc_place = ecx. alloc_caller_location ( file, line, col) ;
@@ -581,7 +607,7 @@ pub fn const_variant_index<'tcx>(
581
607
val : & ' tcx ty:: Const < ' tcx > ,
582
608
) -> VariantIdx {
583
609
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 ) ;
585
611
let op = ecx. eval_const_to_op ( val, None ) . unwrap ( ) ;
586
612
ecx. read_discriminant ( op) . unwrap ( ) . 1
587
613
}
@@ -610,7 +636,9 @@ fn validate_and_turn_into_const<'tcx>(
610
636
key : ty:: ParamEnvAnd < ' tcx , GlobalId < ' tcx > > ,
611
637
) -> :: rustc:: mir:: interpret:: ConstEvalResult < ' tcx > {
612
638
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) ;
614
642
let val = ( || {
615
643
let mplace = ecx. raw_const_to_mplace ( constant) ?;
616
644
let mut ref_tracking = RefTracking :: new ( mplace) ;
@@ -624,8 +652,7 @@ fn validate_and_turn_into_const<'tcx>(
624
652
// Now that we validated, turn this into a proper constant.
625
653
// Statics/promoteds are always `ByRef`, for the rest `op_to_const` decides
626
654
// 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 ( ) {
629
656
let ptr = mplace. ptr . to_ptr ( ) ?;
630
657
Ok ( tcx. mk_const ( ty:: Const {
631
658
val : ty:: ConstKind :: Value ( ConstValue :: ByRef {
@@ -732,12 +759,14 @@ pub fn const_eval_raw_provider<'tcx>(
732
759
return Err ( ErrorHandled :: Reported ) ;
733
760
}
734
761
762
+ let is_static = tcx. is_static ( def_id) ;
763
+
735
764
let span = tcx. def_span ( cid. instance . def_id ( ) ) ;
736
765
let mut ecx = InterpCx :: new (
737
766
tcx. at ( span) ,
738
767
key. param_env ,
739
768
CompileTimeInterpreter :: new ( ) ,
740
- Default :: default ( )
769
+ MemoryExtra { can_access_statics : is_static } ,
741
770
) ;
742
771
743
772
let res = ecx. load_mir ( cid. instance . def , cid. promoted ) ;
@@ -751,7 +780,7 @@ pub fn const_eval_raw_provider<'tcx>(
751
780
} ) . map_err ( |error| {
752
781
let err = error_to_const_error ( & ecx, error) ;
753
782
// errors in statics are always emitted as fatal errors
754
- if tcx . is_static ( def_id ) {
783
+ if is_static {
755
784
// Ensure that if the above error was either `TooGeneric` or `Reported`
756
785
// an error must be reported.
757
786
let v = err. report_as_error ( ecx. tcx , "could not evaluate static initializer" ) ;
0 commit comments