const_prop_lint: ensure we have up-to-date cur_span()
This commit is contained in:
parent
7892e1cedb
commit
9ab4f876a1
@ -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
|
/// this frame (can happen e.g. during frame initialization, and during unwinding on
|
||||||
/// frames without cleanup code).
|
/// frames without cleanup code).
|
||||||
/// We basically abuse `Result` as `Either`.
|
/// We basically abuse `Result` as `Either`.
|
||||||
pub(super) loc: Result<mir::Location, Span>,
|
///
|
||||||
|
/// Needs to be public because ConstProp does unspeakable things to it.
|
||||||
|
pub loc: Result<mir::Location, Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// What we store about a frame in an interpreter backtrace.
|
/// 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]
|
#[inline]
|
||||||
fn layout_tcx_at_span(&self) -> Span {
|
fn layout_tcx_at_span(&self) -> Span {
|
||||||
|
// Using the cheap root span for performance.
|
||||||
self.tcx.span
|
self.tcx.span
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,10 +437,12 @@ fn lint_root(&self, source_info: SourceInfo) -> Option<HirId> {
|
|||||||
source_info.scope.lint_root(self.source_scopes)
|
source_info.scope.lint_root(self.source_scopes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn use_ecx<F, T>(&mut self, f: F) -> Option<T>
|
fn use_ecx<F, T>(&mut self, source_info: SourceInfo, f: F) -> Option<T>
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut Self) -> InterpResult<'tcx, T>,
|
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) {
|
match f(self) {
|
||||||
Ok(val) => Some(val),
|
Ok(val) => Some(val),
|
||||||
Err(error) => {
|
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`.
|
/// Returns the value, if any, of evaluating `place`.
|
||||||
fn eval_place(&mut self, place: Place<'tcx>) -> Option<OpTy<'tcx>> {
|
fn eval_place(&mut self, place: Place<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
|
||||||
trace!("eval_place(place={:?})", place);
|
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`
|
/// 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<OpTy<'tcx>> {
|
|||||||
fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
|
fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
|
||||||
match *op {
|
match *op {
|
||||||
Operand::Constant(ref c) => self.eval_constant(c, source_info),
|
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>,
|
arg: &Operand<'tcx>,
|
||||||
source_info: SourceInfo,
|
source_info: SourceInfo,
|
||||||
) -> Option<()> {
|
) -> 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 val = this.ecx.read_immediate(&this.ecx.eval_operand(arg, None)?)?;
|
||||||
let (_res, overflow, _ty) = this.ecx.overflowing_unary_op(op, &val)?;
|
let (_res, overflow, _ty) = this.ecx.overflowing_unary_op(op, &val)?;
|
||||||
Ok((val, overflow))
|
Ok((val, overflow))
|
||||||
@ -564,8 +566,12 @@ fn check_binary_op(
|
|||||||
right: &Operand<'tcx>,
|
right: &Operand<'tcx>,
|
||||||
source_info: SourceInfo,
|
source_info: SourceInfo,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
let r = self.use_ecx(|this| this.ecx.read_immediate(&this.ecx.eval_operand(right, None)?));
|
let r = self.use_ecx(source_info, |this| {
|
||||||
let l = self.use_ecx(|this| this.ecx.read_immediate(&this.ecx.eval_operand(left, None)?));
|
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.
|
// Check for exceeding shifts *even if* we cannot evaluate the LHS.
|
||||||
if op == BinOp::Shr || op == BinOp::Shl {
|
if op == BinOp::Shr || op == BinOp::Shl {
|
||||||
let r = r?;
|
let r = r?;
|
||||||
@ -602,7 +608,7 @@ fn check_binary_op(
|
|||||||
|
|
||||||
if let (Some(l), Some(r)) = (&l, &r) {
|
if let (Some(l), Some(r)) = (&l, &r) {
|
||||||
// The remaining operators are handled through `overflowing_binary_op`.
|
// 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)?;
|
let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?;
|
||||||
Ok(overflow)
|
Ok(overflow)
|
||||||
})? {
|
})? {
|
||||||
@ -690,7 +696,7 @@ fn const_prop(
|
|||||||
return None;
|
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, .. } => {
|
StatementKind::SetDiscriminant { ref place, .. } => {
|
||||||
match self.ecx.machine.can_const_prop[place.local] {
|
match self.ecx.machine.can_const_prop[place.local] {
|
||||||
ConstPropMode::FullConstProp | ConstPropMode::OnlyInsideOwnBlock => {
|
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);
|
trace!("propped discriminant into {:?}", place);
|
||||||
} else {
|
} else {
|
||||||
Self::remove_const(&mut self.ecx, place.local);
|
Self::remove_const(&mut self.ecx, place.local);
|
||||||
|
Loading…
Reference in New Issue
Block a user