From 9ab4f876a1c5321fe451bf691eb28d87dbf5ff84 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 4 Jun 2022 15:29:51 -0400 Subject: [PATCH] const_prop_lint: ensure we have up-to-date cur_span() --- .../src/interpret/eval_context.rs | 5 +++- .../src/const_prop_lint.rs | 29 ++++++++++++------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 0c954ac6e5f..a82ddfb5ac5 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -126,7 +126,9 @@ pub struct Frame<'mir, 'tcx, Tag: Provenance = AllocId, Extra = ()> { /// this frame (can happen e.g. during frame initialization, and during unwinding on /// frames without cleanup code). /// We basically abuse `Result` as `Either`. - pub(super) loc: Result, + /// + /// Needs to be public because ConstProp does unspeakable things to it. + pub loc: Result, } /// What we store about a frame in an interpreter backtrace. @@ -320,6 +322,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOfHelpers<'tcx> for InterpC #[inline] fn layout_tcx_at_span(&self) -> Span { + // Using the cheap root span for performance. self.tcx.span } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 5fd9db3989d..84fdb136bd4 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -437,10 +437,12 @@ fn lint_root(&self, source_info: SourceInfo) -> Option { source_info.scope.lint_root(self.source_scopes) } - fn use_ecx(&mut self, f: F) -> Option + fn use_ecx(&mut self, source_info: SourceInfo, f: F) -> Option where F: FnOnce(&mut Self) -> InterpResult<'tcx, T>, { + // Overwrite the PC -- whatever the interpreter does to it does not make any sense anyway. + self.ecx.frame_mut().loc = Err(source_info.span); match f(self) { Ok(val) => Some(val), Err(error) => { @@ -501,9 +503,9 @@ fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Opti } /// Returns the value, if any, of evaluating `place`. - fn eval_place(&mut self, place: Place<'tcx>) -> Option> { + fn eval_place(&mut self, place: Place<'tcx>, source_info: SourceInfo) -> Option> { trace!("eval_place(place={:?})", place); - self.use_ecx(|this| this.ecx.eval_place_to_op(place, None)) + self.use_ecx(source_info, |this| this.ecx.eval_place_to_op(place, None)) } /// Returns the value, if any, of evaluating `op`. Calls upon `eval_constant` @@ -511,7 +513,7 @@ fn eval_place(&mut self, place: Place<'tcx>) -> Option> { fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option> { match *op { Operand::Constant(ref c) => self.eval_constant(c, source_info), - Operand::Move(place) | Operand::Copy(place) => self.eval_place(place), + Operand::Move(place) | Operand::Copy(place) => self.eval_place(place, source_info), } } @@ -537,7 +539,7 @@ fn check_unary_op( arg: &Operand<'tcx>, source_info: SourceInfo, ) -> Option<()> { - if let (val, true) = self.use_ecx(|this| { + if let (val, true) = self.use_ecx(source_info, |this| { let val = this.ecx.read_immediate(&this.ecx.eval_operand(arg, None)?)?; let (_res, overflow, _ty) = this.ecx.overflowing_unary_op(op, &val)?; Ok((val, overflow)) @@ -564,8 +566,12 @@ fn check_binary_op( right: &Operand<'tcx>, source_info: SourceInfo, ) -> Option<()> { - let r = self.use_ecx(|this| this.ecx.read_immediate(&this.ecx.eval_operand(right, None)?)); - let l = self.use_ecx(|this| this.ecx.read_immediate(&this.ecx.eval_operand(left, None)?)); + let r = self.use_ecx(source_info, |this| { + this.ecx.read_immediate(&this.ecx.eval_operand(right, None)?) + }); + let l = self.use_ecx(source_info, |this| { + this.ecx.read_immediate(&this.ecx.eval_operand(left, None)?) + }); // Check for exceeding shifts *even if* we cannot evaluate the LHS. if op == BinOp::Shr || op == BinOp::Shl { let r = r?; @@ -602,7 +608,7 @@ fn check_binary_op( if let (Some(l), Some(r)) = (&l, &r) { // The remaining operators are handled through `overflowing_binary_op`. - if self.use_ecx(|this| { + if self.use_ecx(source_info, |this| { let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?; Ok(overflow) })? { @@ -690,7 +696,7 @@ fn const_prop( return None; } - self.use_ecx(|this| this.ecx.eval_rvalue_into_place(rvalue, place)) + self.use_ecx(source_info, |this| this.ecx.eval_rvalue_into_place(rvalue, place)) } } @@ -890,7 +896,10 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { StatementKind::SetDiscriminant { ref place, .. } => { match self.ecx.machine.can_const_prop[place.local] { ConstPropMode::FullConstProp | ConstPropMode::OnlyInsideOwnBlock => { - if self.use_ecx(|this| this.ecx.statement(statement)).is_some() { + if self + .use_ecx(source_info, |this| this.ecx.statement(statement)) + .is_some() + { trace!("propped discriminant into {:?}", place); } else { Self::remove_const(&mut self.ecx, place.local);