Skip to content

Commit 9ab4f87

Browse files
committed
const_prop_lint: ensure we have up-to-date cur_span()
1 parent 7892e1c commit 9ab4f87

File tree

2 files changed

+23
-11
lines changed

2 files changed

+23
-11
lines changed

compiler/rustc_const_eval/src/interpret/eval_context.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,9 @@ pub struct Frame<'mir, 'tcx, Tag: Provenance = AllocId, Extra = ()> {
126126
/// this frame (can happen e.g. during frame initialization, and during unwinding on
127127
/// frames without cleanup code).
128128
/// We basically abuse `Result` as `Either`.
129-
pub(super) loc: Result<mir::Location, Span>,
129+
///
130+
/// Needs to be public because ConstProp does unspeakable things to it.
131+
pub loc: Result<mir::Location, Span>,
130132
}
131133

132134
/// 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
320322

321323
#[inline]
322324
fn layout_tcx_at_span(&self) -> Span {
325+
// Using the cheap root span for performance.
323326
self.tcx.span
324327
}
325328

compiler/rustc_mir_transform/src/const_prop_lint.rs

+19-10
Original file line numberDiff line numberDiff line change
@@ -437,10 +437,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
437437
source_info.scope.lint_root(self.source_scopes)
438438
}
439439

440-
fn use_ecx<F, T>(&mut self, f: F) -> Option<T>
440+
fn use_ecx<F, T>(&mut self, source_info: SourceInfo, f: F) -> Option<T>
441441
where
442442
F: FnOnce(&mut Self) -> InterpResult<'tcx, T>,
443443
{
444+
// Overwrite the PC -- whatever the interpreter does to it does not make any sense anyway.
445+
self.ecx.frame_mut().loc = Err(source_info.span);
444446
match f(self) {
445447
Ok(val) => Some(val),
446448
Err(error) => {
@@ -501,17 +503,17 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
501503
}
502504

503505
/// Returns the value, if any, of evaluating `place`.
504-
fn eval_place(&mut self, place: Place<'tcx>) -> Option<OpTy<'tcx>> {
506+
fn eval_place(&mut self, place: Place<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
505507
trace!("eval_place(place={:?})", place);
506-
self.use_ecx(|this| this.ecx.eval_place_to_op(place, None))
508+
self.use_ecx(source_info, |this| this.ecx.eval_place_to_op(place, None))
507509
}
508510

509511
/// Returns the value, if any, of evaluating `op`. Calls upon `eval_constant`
510512
/// or `eval_place`, depending on the variant of `Operand` used.
511513
fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
512514
match *op {
513515
Operand::Constant(ref c) => self.eval_constant(c, source_info),
514-
Operand::Move(place) | Operand::Copy(place) => self.eval_place(place),
516+
Operand::Move(place) | Operand::Copy(place) => self.eval_place(place, source_info),
515517
}
516518
}
517519

@@ -537,7 +539,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
537539
arg: &Operand<'tcx>,
538540
source_info: SourceInfo,
539541
) -> Option<()> {
540-
if let (val, true) = self.use_ecx(|this| {
542+
if let (val, true) = self.use_ecx(source_info, |this| {
541543
let val = this.ecx.read_immediate(&this.ecx.eval_operand(arg, None)?)?;
542544
let (_res, overflow, _ty) = this.ecx.overflowing_unary_op(op, &val)?;
543545
Ok((val, overflow))
@@ -564,8 +566,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
564566
right: &Operand<'tcx>,
565567
source_info: SourceInfo,
566568
) -> Option<()> {
567-
let r = self.use_ecx(|this| this.ecx.read_immediate(&this.ecx.eval_operand(right, None)?));
568-
let l = self.use_ecx(|this| this.ecx.read_immediate(&this.ecx.eval_operand(left, None)?));
569+
let r = self.use_ecx(source_info, |this| {
570+
this.ecx.read_immediate(&this.ecx.eval_operand(right, None)?)
571+
});
572+
let l = self.use_ecx(source_info, |this| {
573+
this.ecx.read_immediate(&this.ecx.eval_operand(left, None)?)
574+
});
569575
// Check for exceeding shifts *even if* we cannot evaluate the LHS.
570576
if op == BinOp::Shr || op == BinOp::Shl {
571577
let r = r?;
@@ -602,7 +608,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
602608

603609
if let (Some(l), Some(r)) = (&l, &r) {
604610
// The remaining operators are handled through `overflowing_binary_op`.
605-
if self.use_ecx(|this| {
611+
if self.use_ecx(source_info, |this| {
606612
let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?;
607613
Ok(overflow)
608614
})? {
@@ -690,7 +696,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
690696
return None;
691697
}
692698

693-
self.use_ecx(|this| this.ecx.eval_rvalue_into_place(rvalue, place))
699+
self.use_ecx(source_info, |this| this.ecx.eval_rvalue_into_place(rvalue, place))
694700
}
695701
}
696702

@@ -890,7 +896,10 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
890896
StatementKind::SetDiscriminant { ref place, .. } => {
891897
match self.ecx.machine.can_const_prop[place.local] {
892898
ConstPropMode::FullConstProp | ConstPropMode::OnlyInsideOwnBlock => {
893-
if self.use_ecx(|this| this.ecx.statement(statement)).is_some() {
899+
if self
900+
.use_ecx(source_info, |this| this.ecx.statement(statement))
901+
.is_some()
902+
{
894903
trace!("propped discriminant into {:?}", place);
895904
} else {
896905
Self::remove_const(&mut self.ecx, place.local);

0 commit comments

Comments
 (0)