diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index e0be53b80d734..c30c59bbf10c8 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -194,10 +194,9 @@ pub trait Machine<'mir, 'tcx>: Sized { frame.locals[local].access() } - /// Called before a `StaticKind::Static` value is read. - fn before_eval_static( - _ecx: &InterpCx<'mir, 'tcx, Self>, - _place_static: &mir::Static<'tcx>, + /// Called before a `StaticKind::Static` value is accessed. + fn before_access_static( + _allocation: &Allocation, ) -> InterpResult<'tcx> { Ok(()) } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 62b1760508b4c..924474c53175c 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -462,6 +462,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // Make sure we use the ID of the resolved memory, not the lazy one! let id = raw_const.alloc_id; let allocation = tcx.alloc_map.lock().unwrap_memory(id); + + M::before_access_static(allocation)?; Cow::Borrowed(allocation) } } diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index c882f4ef4ddf3..1166ca9bf2444 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -601,8 +601,6 @@ where } StaticKind::Static => { - M::before_eval_static(self, place_static)?; - let ty = place_static.ty; assert!(!ty.needs_subst()); let layout = self.layout_of(ty)?; diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index ce1acc3b7edf9..612822b6d9d34 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -8,7 +8,7 @@ use rustc::hir::def::DefKind; use rustc::hir::def_id::DefId; use rustc::mir::{ AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue, - Local, NullOp, UnOp, StatementKind, Statement, LocalKind, Static, + Local, NullOp, UnOp, StatementKind, Statement, LocalKind, TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp, SourceScope, SourceScopeLocalData, LocalDecl, BasicBlock, }; @@ -17,6 +17,7 @@ use rustc::mir::visit::{ }; use rustc::mir::interpret::{Scalar, InterpResult, PanicInfo}; use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt}; +use syntax::ast::Mutability; use syntax_pos::{Span, DUMMY_SP}; use rustc::ty::subst::InternalSubsts; use rustc_data_structures::fx::FxHashMap; @@ -229,11 +230,16 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { l.access() } - fn before_eval_static( - _ecx: &InterpCx<'mir, 'tcx, Self>, - _place_static: &Static<'tcx>, + fn before_access_static( + allocation: &Allocation, ) -> InterpResult<'tcx> { - throw_unsup_format!("can't eval statics in ConstProp"); + // if the static allocation is mutable or if it has relocations (it may be legal to mutate + // the memory behind that in the future), then we can't const prop it + if allocation.mutability == Mutability::Mutable || allocation.relocations().len() > 0 { + throw_unsup_format!("can't eval mutable statics in ConstProp"); + } + + Ok(()) } fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { diff --git a/src/test/mir-opt/const_prop/read_immutable_static.rs b/src/test/mir-opt/const_prop/read_immutable_static.rs new file mode 100644 index 0000000000000..c2902dbd7c129 --- /dev/null +++ b/src/test/mir-opt/const_prop/read_immutable_static.rs @@ -0,0 +1,29 @@ +// compile-flags: -O + +static FOO: u8 = 2; + +fn main() { + let x = FOO + FOO; +} + +// END RUST SOURCE +// START rustc.main.ConstProp.before.mir +// bb0: { +// ... +// _2 = (FOO: u8); +// ... +// _3 = (FOO: u8); +// _1 = Add(move _2, move _3); +// ... +// } +// END rustc.main.ConstProp.before.mir +// START rustc.main.ConstProp.after.mir +// bb0: { +// ... +// _2 = const 2u8; +// ... +// _3 = const 2u8; +// _1 = Add(move _2, move _3); +// ... +// } +// END rustc.main.ConstProp.after.mir