diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 9184173e402e..a87b00263e5c 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -157,14 +157,19 @@ struct ConstPropMachine<'mir, 'tcx> { written_only_inside_own_block_locals: FxHashSet, /// Locals that need to be cleared after every block terminates. only_propagate_inside_block_locals: BitSet, + can_const_prop: IndexVec, } impl<'mir, 'tcx> ConstPropMachine<'mir, 'tcx> { - fn new(only_propagate_inside_block_locals: BitSet) -> Self { + fn new( + only_propagate_inside_block_locals: BitSet, + can_const_prop: IndexVec, + ) -> Self { Self { stack: Vec::new(), written_only_inside_own_block_locals: Default::default(), only_propagate_inside_block_locals, + can_const_prop, } } } @@ -243,6 +248,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> local: Local, ) -> InterpResult<'tcx, Result<&'a mut LocalValue, MemPlace>> { + if ecx.machine.can_const_prop[local] == ConstPropMode::NoPropagation { + throw_machine_stop_str!("tried to write to a local that is marked as not propagatable") + } if frame == 0 && ecx.machine.only_propagate_inside_block_locals.contains(local) { ecx.machine.written_only_inside_own_block_locals.insert(local); } @@ -287,7 +295,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> struct ConstPropagator<'mir, 'tcx> { ecx: InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>, tcx: TyCtxt<'tcx>, - can_const_prop: IndexVec, param_env: ParamEnv<'tcx>, // FIXME(eddyb) avoid cloning these two fields more than once, // by accessing them through `ecx` instead. @@ -347,7 +354,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { tcx, span, param_env, - ConstPropMachine::new(only_propagate_inside_block_locals), + ConstPropMachine::new(only_propagate_inside_block_locals, can_const_prop), (), ); @@ -373,7 +380,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { ecx, tcx, param_env, - can_const_prop, // FIXME(eddyb) avoid cloning these two fields more than once, // by accessing them through `ecx` instead. source_scopes: body.source_scopes.clone(), @@ -1031,7 +1037,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { let source_info = statement.source_info; self.source_info = Some(source_info); if let StatementKind::Assign(box (place, ref mut rval)) = statement.kind { - let can_const_prop = self.can_const_prop[place.local]; + let can_const_prop = self.ecx.machine.can_const_prop[place.local]; if let Some(()) = self.const_prop(rval, source_info, place) { // This will return None if the above `const_prop` invocation only "wrote" a // type whose creation requires no write. E.g. a generator whose initial state diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff index e78bc31b7748..6e2ee0957ab3 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff @@ -23,15 +23,13 @@ // + ty: i32 // + val: Value(Scalar(0x0000002a)) // mir::Constant -- // + span: $DIR/mutable_variable_aggregate_mut_ref.rs:5:18: 5:20 -+ // + span: $DIR/mutable_variable_aggregate_mut_ref.rs:5:17: 5:25 + // + span: $DIR/mutable_variable_aggregate_mut_ref.rs:5:18: 5:20 // + literal: Const { ty: i32, val: Value(Scalar(0x0000002a)) } // ty::Const // + ty: i32 // + val: Value(Scalar(0x0000002b)) // mir::Constant -- // + span: $DIR/mutable_variable_aggregate_mut_ref.rs:5:22: 5:24 -+ // + span: $DIR/mutable_variable_aggregate_mut_ref.rs:5:17: 5:25 + // + span: $DIR/mutable_variable_aggregate_mut_ref.rs:5:22: 5:24 // + literal: Const { ty: i32, val: Value(Scalar(0x0000002b)) } StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:6:9: 6:10 _2 = &mut _1; // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:6:13: 6:19