From 0633a0e3801e4efc9ab07bf811e442bd379ce93a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 8 Feb 2020 22:21:20 +0100 Subject: [PATCH 1/9] remove Panic variant from InterpError --- src/librustc/mir/interpret/error.rs | 22 +++-- src/librustc/mir/interpret/mod.rs | 14 ---- src/librustc_mir/const_eval/error.rs | 21 +++-- src/librustc_mir/const_eval/machine.rs | 62 ++++++++++---- src/librustc_mir/interpret/intrinsics.rs | 26 ------ .../interpret/intrinsics/caller_location.rs | 12 +-- src/librustc_mir/transform/const_prop.rs | 83 +++++++++---------- 7 files changed, 117 insertions(+), 123 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 86e7bb28e0069..e819dfbacd898 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -139,7 +139,6 @@ impl<'tcx> ConstEvalErr<'tcx> { lint_root: Option, ) -> Result<(), ErrorHandled> { let must_error = match self.error { - InterpError::MachineStop(_) => bug!("CTFE does not stop"), err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => { return Err(ErrorHandled::TooGeneric); } @@ -149,9 +148,18 @@ impl<'tcx> ConstEvalErr<'tcx> { }; trace!("reporting const eval failure at {:?}", self.span); + let err_msg = match &self.error { + InterpError::MachineStop(msg) => { + // A custom error (`ConstEvalErrKind` in `librustc_mir/interp/const_eval/error.rs`). + // Should be turned into a string by now. + msg.downcast_ref::().expect("invalid MachineStop payload").clone() + } + err => err.to_string(), + }; + let add_span_labels = |err: &mut DiagnosticBuilder<'_>| { if !must_error { - err.span_label(self.span, self.error.to_string()); + err.span_label(self.span, err_msg.clone()); } // Skip the last, which is just the environment of the constant. The stacktrace // is sometimes empty because we create "fake" eval contexts in CTFE to do work @@ -183,7 +191,7 @@ impl<'tcx> ConstEvalErr<'tcx> { ); } else { let mut err = if must_error { - struct_error(tcx, &self.error.to_string()) + struct_error(tcx, &err_msg) } else { struct_error(tcx, message) }; @@ -259,6 +267,9 @@ impl<'tcx> From> for InterpErrorInfo<'tcx> { } } +/// Information about a panic. +/// +/// FIXME: this is not actually an InterpError, and should probably be moved to another module. #[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)] pub enum PanicInfo { Panic { msg: Symbol, line: u32, col: u32, file: Symbol }, @@ -616,8 +627,6 @@ impl fmt::Debug for ResourceExhaustionInfo { } pub enum InterpError<'tcx> { - /// The program panicked. - Panic(PanicInfo), /// The program caused undefined behavior. UndefinedBehavior(UndefinedBehaviorInfo), /// The program did something the interpreter does not support (some of these *might* be UB @@ -650,8 +659,7 @@ impl fmt::Debug for InterpError<'_> { InvalidProgram(ref msg) => write!(f, "{:?}", msg), UndefinedBehavior(ref msg) => write!(f, "{:?}", msg), ResourceExhaustion(ref msg) => write!(f, "{:?}", msg), - Panic(ref msg) => write!(f, "{:?}", msg), - MachineStop(_) => write!(f, "machine caused execution to stop"), + MachineStop(_) => bug!("unhandled MachineStop"), } } } diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index 54e196f4b3341..b4cfd86015296 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -37,15 +37,6 @@ macro_rules! err_ub_format { ($($tt:tt)*) => { err_ub!(Ub(format!($($tt)*))) }; } -#[macro_export] -macro_rules! err_panic { - ($($tt:tt)*) => { - $crate::mir::interpret::InterpError::Panic( - $crate::mir::interpret::PanicInfo::$($tt)* - ) - }; -} - #[macro_export] macro_rules! err_exhaust { ($($tt:tt)*) => { @@ -80,11 +71,6 @@ macro_rules! throw_ub_format { ($($tt:tt)*) => { throw_ub!(Ub(format!($($tt)*))) }; } -#[macro_export] -macro_rules! throw_panic { - ($($tt:tt)*) => { return Err(err_panic!($($tt)*).into()) }; -} - #[macro_export] macro_rules! throw_exhaust { ($($tt:tt)*) => { return Err(err_exhaust!($($tt)*).into()) }; diff --git a/src/librustc_mir/const_eval/error.rs b/src/librustc_mir/const_eval/error.rs index c2db3c31f85be..e0e7854609971 100644 --- a/src/librustc_mir/const_eval/error.rs +++ b/src/librustc_mir/const_eval/error.rs @@ -2,32 +2,39 @@ use std::error::Error; use std::fmt; use super::InterpCx; -use crate::interpret::{ConstEvalErr, InterpErrorInfo, Machine}; +use crate::interpret::{ConstEvalErr, InterpError, InterpErrorInfo, Machine, PanicInfo}; + +/// The CTFE machine has some custom error kinds. #[derive(Clone, Debug)] -pub enum ConstEvalError { +pub enum ConstEvalErrKind { NeedsRfc(String), ConstAccessesStatic, + Panic(PanicInfo), } -impl<'tcx> Into> for ConstEvalError { +// The errors become `MachineStop` with plain strings when being raised. +// `ConstEvalErr` (in `librustc/mir/interpret/error.rs`) knows to +// handle these. +impl<'tcx> Into> for ConstEvalErrKind { fn into(self) -> InterpErrorInfo<'tcx> { - err_unsup!(Unsupported(self.to_string())).into() + InterpError::MachineStop(Box::new(self.to_string())).into() } } -impl fmt::Display for ConstEvalError { +impl fmt::Display for ConstEvalErrKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use self::ConstEvalError::*; + use self::ConstEvalErrKind::*; match *self { NeedsRfc(ref msg) => { write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg) } ConstAccessesStatic => write!(f, "constant accesses static"), + Panic(ref msg) => write!(f, "{:?}", msg), } } } -impl Error for ConstEvalError {} +impl Error for ConstEvalErrKind {} /// Turn an interpreter error into something to report to the user. /// As a side-effect, if RUSTC_CTFE_BACKTRACE is set, this prints the backtrace. diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index 1aed91baba6a8..688eee05ddae7 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -9,10 +9,11 @@ use std::hash::Hash; use rustc_data_structures::fx::FxHashMap; use rustc_span::source_map::Span; +use rustc_span::symbol::Symbol; use crate::interpret::{ self, snapshot, AllocId, Allocation, AssertMessage, GlobalId, ImmTy, InterpCx, InterpResult, - Memory, MemoryKind, OpTy, PlaceTy, Pointer, Scalar, + Memory, MemoryKind, OpTy, PanicInfo, PlaceTy, Pointer, Scalar, }; use super::error::*; @@ -56,6 +57,32 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { self.dump_place(*dest); return Ok(true); } + + /// "Intercept" a function call to a panic-related function + /// because we have something special to do for it. + /// Returns `true` if an intercept happened. + pub fn hook_panic_fn( + &mut self, + span: Span, + instance: ty::Instance<'tcx>, + args: &[OpTy<'tcx>], + ) -> InterpResult<'tcx, bool> { + let def_id = instance.def_id(); + if Some(def_id) == self.tcx.lang_items().panic_fn() + || Some(def_id) == self.tcx.lang_items().begin_panic_fn() + { + // &'static str + assert!(args.len() == 1); + + let msg_place = self.deref_operand(args[0])?; + let msg = Symbol::intern(self.read_str(msg_place)?); + let span = self.find_closest_untracked_caller_location().unwrap_or(span); + let (file, line, col) = self.location_triple_for_span(span); + Err(ConstEvalErrKind::Panic(PanicInfo::Panic { msg, file, line, col }).into()) + } else { + Ok(false) + } + } } /// Number of steps until the detector even starts doing anything. @@ -212,7 +239,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, Ok(body) => *body, Err(err) => { if let err_unsup!(NoMirFor(ref path)) = err.kind { - return Err(ConstEvalError::NeedsRfc(format!( + return Err(ConstEvalErrKind::NeedsRfc(format!( "calling extern function `{}`", path )) @@ -246,7 +273,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } // An intrinsic that we do not support let intrinsic_name = ecx.tcx.item_name(instance.def_id()); - Err(ConstEvalError::NeedsRfc(format!("calling intrinsic `{}`", intrinsic_name)).into()) + Err(ConstEvalErrKind::NeedsRfc(format!("calling intrinsic `{}`", intrinsic_name)).into()) } fn assert_panic( @@ -256,7 +283,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, _unwind: Option, ) -> InterpResult<'tcx> { use rustc::mir::interpret::PanicInfo::*; - Err(match msg { + // Convert `PanicInfo` to `PanicInfo`. + let err = match msg { BoundsCheck { ref len, ref index } => { let len = ecx .read_immediate(ecx.eval_operand(len, None)?) @@ -268,21 +296,21 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, .expect("can't eval index") .to_scalar()? .to_machine_usize(&*ecx)?; - err_panic!(BoundsCheck { len, index }) + BoundsCheck { len, index } } - Overflow(op) => err_panic!(Overflow(*op)), - OverflowNeg => err_panic!(OverflowNeg), - DivisionByZero => err_panic!(DivisionByZero), - RemainderByZero => err_panic!(RemainderByZero), - ResumedAfterReturn(generator_kind) => err_panic!(ResumedAfterReturn(*generator_kind)), - ResumedAfterPanic(generator_kind) => err_panic!(ResumedAfterPanic(*generator_kind)), + Overflow(op) => Overflow(*op), + OverflowNeg => OverflowNeg, + DivisionByZero => DivisionByZero, + RemainderByZero => RemainderByZero, + ResumedAfterReturn(generator_kind) => ResumedAfterReturn(*generator_kind), + ResumedAfterPanic(generator_kind) => ResumedAfterPanic(*generator_kind), Panic { .. } => bug!("`Panic` variant cannot occur in MIR"), - } - .into()) + }; + Err(ConstEvalErrKind::Panic(err).into()) } fn ptr_to_int(_mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx, u64> { - Err(ConstEvalError::NeedsRfc("pointer-to-integer cast".to_string()).into()) + Err(ConstEvalErrKind::NeedsRfc("pointer-to-integer cast".to_string()).into()) } fn binary_ptr_op( @@ -291,7 +319,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, _left: ImmTy<'tcx>, _right: ImmTy<'tcx>, ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { - Err(ConstEvalError::NeedsRfc("pointer arithmetic or comparison".to_string()).into()) + Err(ConstEvalErrKind::NeedsRfc("pointer arithmetic or comparison".to_string()).into()) } fn find_foreign_static( @@ -321,7 +349,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, _ecx: &mut InterpCx<'mir, 'tcx, Self>, _dest: PlaceTy<'tcx>, ) -> InterpResult<'tcx> { - Err(ConstEvalError::NeedsRfc("heap allocations via `box` keyword".to_string()).into()) + Err(ConstEvalErrKind::NeedsRfc("heap allocations via `box` keyword".to_string()).into()) } fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { @@ -355,7 +383,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, if memory_extra.can_access_statics { Ok(()) } else { - Err(ConstEvalError::ConstAccessesStatic.into()) + Err(ConstEvalErrKind::ConstAccessesStatic.into()) } } } diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index f85da760ada6d..a83b541279061 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -376,32 +376,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(true) } - /// "Intercept" a function call to a panic-related function - /// because we have something special to do for it. - /// Returns `true` if an intercept happened. - pub fn hook_panic_fn( - &mut self, - span: Span, - instance: ty::Instance<'tcx>, - args: &[OpTy<'tcx, M::PointerTag>], - ) -> InterpResult<'tcx, bool> { - let def_id = instance.def_id(); - if Some(def_id) == self.tcx.lang_items().panic_fn() - || Some(def_id) == self.tcx.lang_items().begin_panic_fn() - { - // &'static str - assert!(args.len() == 1); - - let msg_place = self.deref_operand(args[0])?; - let msg = Symbol::intern(self.read_str(msg_place)?); - let span = self.find_closest_untracked_caller_location().unwrap_or(span); - let (file, line, col) = self.location_triple_for_span(span); - throw_panic!(Panic { msg, file, line, col }) - } else { - return Ok(false); - } - } - pub fn exact_div( &mut self, a: ImmTy<'tcx, M::PointerTag>, diff --git a/src/librustc_mir/interpret/intrinsics/caller_location.rs b/src/librustc_mir/interpret/intrinsics/caller_location.rs index 0525108d2d129..566601f0cae28 100644 --- a/src/librustc_mir/interpret/intrinsics/caller_location.rs +++ b/src/librustc_mir/interpret/intrinsics/caller_location.rs @@ -54,12 +54,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { location } - pub fn alloc_caller_location_for_span(&mut self, span: Span) -> MPlaceTy<'tcx, M::PointerTag> { - let (file, line, column) = self.location_triple_for_span(span); - self.alloc_caller_location(file, line, column) - } - - pub(super) fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) { + crate fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) { let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span); let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo()); ( @@ -68,4 +63,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { caller.col_display as u32 + 1, ) } + + pub fn alloc_caller_location_for_span(&mut self, span: Span) -> MPlaceTy<'tcx, M::PointerTag> { + let (file, line, column) = self.location_triple_for_span(span); + self.alloc_caller_location(file, line, column) + } } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index a7da4f7c164fe..43a6382646f3f 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use std::cell::Cell; -use rustc::mir::interpret::{InterpResult, PanicInfo, Scalar}; +use rustc::mir::interpret::{InterpError, InterpResult, PanicInfo, Scalar}; use rustc::mir::visit::{ MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, }; @@ -25,7 +25,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::HirId; use rustc_index::vec::IndexVec; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::Span; use syntax::ast::Mutability; use crate::const_eval::error_to_const_error; @@ -410,15 +410,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - fn use_ecx(&mut self, source_info: SourceInfo, f: F) -> Option + fn use_ecx(&mut self, f: F) -> Option where F: FnOnce(&mut Self) -> InterpResult<'tcx, T>, { - self.ecx.tcx.span = source_info.span; - // FIXME(eddyb) move this to the `Panic(_)` error case, so that - // `f(self)` is always called, and that the only difference when the - // scope's `local_data` is missing, is that the lint isn't emitted. - let lint_root = self.lint_root(source_info)?; let r = match f(self) { Ok(val) => Some(val), Err(error) => { @@ -447,20 +442,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { | ResourceExhaustion(_) => { // Ignore these errors. } - Panic(_) => { - let diagnostic = error_to_const_error(&self.ecx, error); - diagnostic.report_as_lint( - self.ecx.tcx, - "this expression will panic at runtime", - lint_root, - None, - ); - } } None } }; - self.ecx.tcx.span = DUMMY_SP; r } @@ -504,37 +489,47 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option> { + fn eval_place(&mut self, place: &Place<'tcx>) -> Option> { trace!("eval_place(place={:?})", place); - self.use_ecx(source_info, |this| this.ecx.eval_place_to_op(place, None)) + self.use_ecx(|this| this.ecx.eval_place_to_op(place, None)) } 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(ref place) | Operand::Copy(ref place) => { - self.eval_place(place, source_info) - } + Operand::Move(ref place) | Operand::Copy(ref place) => self.eval_place(place), } } + fn report_panic_as_lint(&self, source_info: SourceInfo, panic: PanicInfo) -> Option<()> { + // Somewhat convoluted way to re-use the CTFE error reporting code. + let lint_root = self.lint_root(source_info)?; + let error = InterpError::MachineStop(Box::new(format!("{:?}", panic))); + let mut diagnostic = error_to_const_error(&self.ecx, error.into()); + diagnostic.span = source_info.span; // fix the span + diagnostic.report_as_lint( + self.tcx.at(source_info.span), + "this expression will panic at runtime", + lint_root, + None, + ); + None + } + fn check_unary_op( &mut self, op: UnOp, arg: &Operand<'tcx>, source_info: SourceInfo, ) -> Option<()> { - self.use_ecx(source_info, |this| { + if self.use_ecx(|this| { let val = this.ecx.read_immediate(this.ecx.eval_operand(arg, None)?)?; let (_res, overflow, _ty) = this.ecx.overflowing_unary_op(op, val)?; - - if overflow { - assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow"); - throw_panic!(OverflowNeg); - } - - Ok(()) - })?; + Ok(overflow) + })? { + assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow"); + self.report_panic_as_lint(source_info, PanicInfo::OverflowNeg)?; + } Some(()) } @@ -548,9 +543,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { place_layout: TyLayout<'tcx>, overflow_check: bool, ) -> Option<()> { - let r = self.use_ecx(source_info, |this| { - this.ecx.read_immediate(this.ecx.eval_operand(right, None)?) - })?; + let r = + self.use_ecx(|this| this.ecx.read_immediate(this.ecx.eval_operand(right, None)?))?; if op == BinOp::Shr || op == BinOp::Shl { let left_bits = place_layout.size.bits(); let right_size = r.layout.size; @@ -575,16 +569,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // in MIR. However, if overflow checking is disabled, then there won't be any // `Assert` statement and so we have to do additional checking here. if !overflow_check { - self.use_ecx(source_info, |this| { + if self.use_ecx(|this| { let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?; let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?; - - if overflow { - throw_panic!(Overflow(op)); - } - - Ok(()) - })?; + Ok(overflow) + })? { + self.report_panic_as_lint(source_info, PanicInfo::Overflow(op))?; + } } Some(()) @@ -642,7 +633,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { _ => {} } - self.use_ecx(source_info, |this| { + self.use_ecx(|this| { trace!("calling eval_rvalue_into_place(rvalue = {:?}, place = {:?})", rvalue, place); this.ecx.eval_rvalue_into_place(rvalue, place)?; Ok(()) @@ -675,7 +666,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } // FIXME> figure out what tho do when try_read_immediate fails - let imm = self.use_ecx(source_info, |this| this.ecx.try_read_immediate(value)); + let imm = self.use_ecx(|this| this.ecx.try_read_immediate(value)); if let Some(Ok(imm)) = imm { match *imm { @@ -698,7 +689,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { if let ty::Tuple(substs) = ty { // Only do it if tuple is also a pair with two scalars if substs.len() == 2 { - let opt_ty1_ty2 = self.use_ecx(source_info, |this| { + let opt_ty1_ty2 = self.use_ecx(|this| { let ty1 = substs[0].expect_ty(); let ty2 = substs[1].expect_ty(); let ty_is_scalar = |ty| { From c5709ff6b779d88c0d432f6ed8731fde6e55c090 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 8 Feb 2020 23:01:36 +0100 Subject: [PATCH 2/9] const-prop: handle overflow_check consistently for all operators --- src/librustc_mir/transform/const_prop.rs | 25 ++++++++++-------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 43a6382646f3f..5c6c003b3a698 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -541,7 +541,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { right: &Operand<'tcx>, source_info: SourceInfo, place_layout: TyLayout<'tcx>, - overflow_check: bool, ) -> Option<()> { let r = self.use_ecx(|this| this.ecx.read_immediate(this.ecx.eval_operand(right, None)?))?; @@ -564,18 +563,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - // If overflow checking is enabled (like in debug mode by default), - // then we'll already catch overflow when we evaluate the `Assert` statement - // in MIR. However, if overflow checking is disabled, then there won't be any - // `Assert` statement and so we have to do additional checking here. - if !overflow_check { - if self.use_ecx(|this| { - let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?; - let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?; - Ok(overflow) - })? { - self.report_panic_as_lint(source_info, PanicInfo::Overflow(op))?; - } + // The remaining operators are handled through `overflowing_binary_op`. + // FIXME: Why do we not also do this for `Shr` and `Shl`? + if self.use_ecx(|this| { + let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?; + let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?; + Ok(overflow) + })? { + self.report_panic_as_lint(source_info, PanicInfo::Overflow(op))?; } Some(()) @@ -618,9 +613,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // Additional checking: check for overflows on integer binary operations and report // them to the user as lints. - Rvalue::BinaryOp(op, left, right) => { + Rvalue::BinaryOp(op, left, right) if !overflow_check => { trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right); - self.check_binary_op(*op, left, right, source_info, place_layout, overflow_check)?; + self.check_binary_op(*op, left, right, source_info, place_layout)?; } // Do not try creating references (#67862) From f3ff02bdd85255ad75bae40aad53e520e37a8e4a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 Feb 2020 16:51:36 +0100 Subject: [PATCH 3/9] remove PanicInfo::Panic variant that MIR does not use or need --- src/librustc/mir/interpret/error.rs | 9 ++------- src/librustc/mir/mod.rs | 6 ++---- src/librustc/mir/visit.rs | 2 +- src/librustc_mir/const_eval/error.rs | 10 ++++++++-- src/librustc_mir/const_eval/machine.rs | 7 +++---- 5 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index e819dfbacd898..da8c0bf266f49 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -11,7 +11,6 @@ use hir::GeneratorKind; use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_hir as hir; use rustc_macros::HashStable; -use rustc_span::symbol::Symbol; use rustc_span::{Pos, Span}; use rustc_target::spec::abi::Abi; use std::{any::Any, env, fmt}; @@ -272,7 +271,6 @@ impl<'tcx> From> for InterpErrorInfo<'tcx> { /// FIXME: this is not actually an InterpError, and should probably be moved to another module. #[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)] pub enum PanicInfo { - Panic { msg: Symbol, line: u32, col: u32, file: Symbol }, BoundsCheck { len: O, index: O }, Overflow(mir::BinOp), OverflowNeg, @@ -288,7 +286,7 @@ pub type AssertMessage<'tcx> = PanicInfo>; impl PanicInfo { /// Getting a description does not require `O` to be printable, and does not /// require allocation. - /// The caller is expected to handle `Panic` and `BoundsCheck` separately. + /// The caller is expected to handle `BoundsCheck` separately. pub fn description(&self) -> &'static str { use PanicInfo::*; match self { @@ -307,7 +305,7 @@ impl PanicInfo { ResumedAfterReturn(GeneratorKind::Async(_)) => "`async fn` resumed after completion", ResumedAfterPanic(GeneratorKind::Gen) => "generator resumed after panicking", ResumedAfterPanic(GeneratorKind::Async(_)) => "`async fn` resumed after panicking", - Panic { .. } | BoundsCheck { .. } => bug!("Unexpected PanicInfo"), + BoundsCheck { .. } => bug!("Unexpected PanicInfo"), } } } @@ -316,9 +314,6 @@ impl fmt::Debug for PanicInfo { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use PanicInfo::*; match self { - Panic { ref msg, line, col, ref file } => { - write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col) - } BoundsCheck { ref len, ref index } => { write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index) } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index f6c7174649fe8..0501124155725 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2671,8 +2671,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { BoundsCheck { ref len, ref index } => { BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) } } - Panic { .. } - | Overflow(_) + Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero @@ -2721,8 +2720,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { BoundsCheck { ref len, ref index } => { len.visit_with(visitor) || index.visit_with(visitor) } - Panic { .. } - | Overflow(_) + Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 2f094516a35d9..555beaa8ca798 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -539,7 +539,7 @@ macro_rules! make_mir_visitor { self.visit_operand(len, location); self.visit_operand(index, location); } - Panic { .. } | Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero | + Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero | ResumedAfterReturn(_) | ResumedAfterPanic(_) => { // Nothing to visit } diff --git a/src/librustc_mir/const_eval/error.rs b/src/librustc_mir/const_eval/error.rs index e0e7854609971..edf0f0a7dbe7c 100644 --- a/src/librustc_mir/const_eval/error.rs +++ b/src/librustc_mir/const_eval/error.rs @@ -1,6 +1,8 @@ use std::error::Error; use std::fmt; +use rustc_span::Symbol; + use super::InterpCx; use crate::interpret::{ConstEvalErr, InterpError, InterpErrorInfo, Machine, PanicInfo}; @@ -9,7 +11,8 @@ use crate::interpret::{ConstEvalErr, InterpError, InterpErrorInfo, Machine, Pani pub enum ConstEvalErrKind { NeedsRfc(String), ConstAccessesStatic, - Panic(PanicInfo), + AssertFailure(PanicInfo), + Panic { msg: Symbol, line: u32, col: u32, file: Symbol }, } // The errors become `MachineStop` with plain strings when being raised. @@ -29,7 +32,10 @@ impl fmt::Display for ConstEvalErrKind { write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg) } ConstAccessesStatic => write!(f, "constant accesses static"), - Panic(ref msg) => write!(f, "{:?}", msg), + AssertFailure(ref msg) => write!(f, "{:?}", msg), + Panic { msg, line, col, file } => { + write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col) + } } } } diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index 688eee05ddae7..e0f146c6dc0a5 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -13,7 +13,7 @@ use rustc_span::symbol::Symbol; use crate::interpret::{ self, snapshot, AllocId, Allocation, AssertMessage, GlobalId, ImmTy, InterpCx, InterpResult, - Memory, MemoryKind, OpTy, PanicInfo, PlaceTy, Pointer, Scalar, + Memory, MemoryKind, OpTy, PlaceTy, Pointer, Scalar, }; use super::error::*; @@ -78,7 +78,7 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { let msg = Symbol::intern(self.read_str(msg_place)?); let span = self.find_closest_untracked_caller_location().unwrap_or(span); let (file, line, col) = self.location_triple_for_span(span); - Err(ConstEvalErrKind::Panic(PanicInfo::Panic { msg, file, line, col }).into()) + Err(ConstEvalErrKind::Panic { msg, file, line, col }.into()) } else { Ok(false) } @@ -304,9 +304,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, RemainderByZero => RemainderByZero, ResumedAfterReturn(generator_kind) => ResumedAfterReturn(*generator_kind), ResumedAfterPanic(generator_kind) => ResumedAfterPanic(*generator_kind), - Panic { .. } => bug!("`Panic` variant cannot occur in MIR"), }; - Err(ConstEvalErrKind::Panic(err).into()) + Err(ConstEvalErrKind::AssertFailure(err).into()) } fn ptr_to_int(_mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx, u64> { From 17a8cfd605fb8d43dc61496a522cf3b84988d69d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 Feb 2020 16:54:40 +0100 Subject: [PATCH 4/9] no need for hook_panic_fn to return a bool --- src/librustc_mir/const_eval/machine.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index e0f146c6dc0a5..7fd96ec2d1a5f 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -60,13 +60,13 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { /// "Intercept" a function call to a panic-related function /// because we have something special to do for it. - /// Returns `true` if an intercept happened. - pub fn hook_panic_fn( + /// If this returns successfully (`Ok`), the function should just be evaluated normally. + fn hook_panic_fn( &mut self, span: Span, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx>], - ) -> InterpResult<'tcx, bool> { + ) -> InterpResult<'tcx> { let def_id = instance.def_id(); if Some(def_id) == self.tcx.lang_items().panic_fn() || Some(def_id) == self.tcx.lang_items().begin_panic_fn() @@ -80,7 +80,7 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { let (file, line, col) = self.location_triple_for_span(span); Err(ConstEvalErrKind::Panic { msg, file, line, col }.into()) } else { - Ok(false) + Ok(()) } } } @@ -225,13 +225,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } } else { // Some functions we support even if they are non-const -- but avoid testing - // that for const fn! We certainly do *not* want to actually call the fn + // that for const fn! + ecx.hook_panic_fn(span, instance, args)?; + // We certainly do *not* want to actually call the fn // though, so be sure we return here. - return if ecx.hook_panic_fn(span, instance, args)? { - Ok(None) - } else { - throw_unsup_format!("calling non-const function `{}`", instance) - }; + throw_unsup_format!("calling non-const function `{}`", instance) } } // This is a const fn. Call it. From 6457b29104028bbb3af5efeefed7343d85576320 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 10 Feb 2020 20:53:01 +0100 Subject: [PATCH 5/9] move PanicInfo to mir module --- src/librustc/mir/interpret/error.rs | 57 ------------------- src/librustc/mir/interpret/mod.rs | 6 +- src/librustc/mir/mod.rs | 57 ++++++++++++++++++- src/librustc/mir/visit.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 2 +- src/librustc_mir/borrow_check/invalidation.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 2 +- .../borrow_check/type_check/mod.rs | 2 +- src/librustc_mir/const_eval/error.rs | 3 +- src/librustc_mir/const_eval/machine.rs | 7 ++- src/librustc_mir/interpret/machine.rs | 6 +- src/librustc_mir/transform/const_prop.rs | 6 +- src/librustc_mir/transform/generator.rs | 2 +- src/librustc_mir_build/build/expr/as_place.rs | 2 +- .../build/expr/as_rvalue.rs | 2 +- 15 files changed, 78 insertions(+), 80 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index da8c0bf266f49..a7e769b8b9675 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -7,7 +7,6 @@ use crate::ty::query::TyCtxtAt; use crate::ty::{self, layout, Ty}; use backtrace::Backtrace; -use hir::GeneratorKind; use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_hir as hir; use rustc_macros::HashStable; @@ -266,62 +265,6 @@ impl<'tcx> From> for InterpErrorInfo<'tcx> { } } -/// Information about a panic. -/// -/// FIXME: this is not actually an InterpError, and should probably be moved to another module. -#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)] -pub enum PanicInfo { - BoundsCheck { len: O, index: O }, - Overflow(mir::BinOp), - OverflowNeg, - DivisionByZero, - RemainderByZero, - ResumedAfterReturn(GeneratorKind), - ResumedAfterPanic(GeneratorKind), -} - -/// Type for MIR `Assert` terminator error messages. -pub type AssertMessage<'tcx> = PanicInfo>; - -impl PanicInfo { - /// Getting a description does not require `O` to be printable, and does not - /// require allocation. - /// The caller is expected to handle `BoundsCheck` separately. - pub fn description(&self) -> &'static str { - use PanicInfo::*; - match self { - Overflow(mir::BinOp::Add) => "attempt to add with overflow", - Overflow(mir::BinOp::Sub) => "attempt to subtract with overflow", - Overflow(mir::BinOp::Mul) => "attempt to multiply with overflow", - Overflow(mir::BinOp::Div) => "attempt to divide with overflow", - Overflow(mir::BinOp::Rem) => "attempt to calculate the remainder with overflow", - OverflowNeg => "attempt to negate with overflow", - Overflow(mir::BinOp::Shr) => "attempt to shift right with overflow", - Overflow(mir::BinOp::Shl) => "attempt to shift left with overflow", - Overflow(op) => bug!("{:?} cannot overflow", op), - DivisionByZero => "attempt to divide by zero", - RemainderByZero => "attempt to calculate the remainder with a divisor of zero", - ResumedAfterReturn(GeneratorKind::Gen) => "generator resumed after completion", - ResumedAfterReturn(GeneratorKind::Async(_)) => "`async fn` resumed after completion", - ResumedAfterPanic(GeneratorKind::Gen) => "generator resumed after panicking", - ResumedAfterPanic(GeneratorKind::Async(_)) => "`async fn` resumed after panicking", - BoundsCheck { .. } => bug!("Unexpected PanicInfo"), - } - } -} - -impl fmt::Debug for PanicInfo { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use PanicInfo::*; - match self { - BoundsCheck { ref len, ref index } => { - write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index) - } - _ => write!(f, "{}", self.description()), - } - } -} - /// Error information for when the program we executed turned out not to actually be a valid /// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp /// where we work on generic code or execution does not have all information available. diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index b4cfd86015296..f0879bdd8ae9b 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -90,9 +90,9 @@ mod queries; mod value; pub use self::error::{ - struct_error, AssertMessage, ConstEvalErr, ConstEvalRawResult, ConstEvalResult, ErrorHandled, - FrameInfo, InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, PanicInfo, - ResourceExhaustionInfo, UndefinedBehaviorInfo, UnsupportedOpInfo, + struct_error, ConstEvalErr, ConstEvalRawResult, ConstEvalResult, ErrorHandled, FrameInfo, + InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, ResourceExhaustionInfo, + UndefinedBehaviorInfo, UnsupportedOpInfo, }; pub use self::value::{get_slice_bytes, ConstValue, RawConst, Scalar, ScalarMaybeUndef}; diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 0501124155725..8d224b6d7394f 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2,7 +2,7 @@ //! //! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/index.html -use crate::mir::interpret::{GlobalAlloc, PanicInfo, Scalar}; +use crate::mir::interpret::{GlobalAlloc, Scalar}; use crate::mir::visit::MirVisitable; use crate::ty::adjustment::PointerCast; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; @@ -36,7 +36,6 @@ pub use syntax::ast::Mutability; use syntax::ast::Name; pub use self::cache::{BodyAndCache, ReadOnlyBodyAndCache}; -pub use self::interpret::AssertMessage; pub use self::query::*; pub use crate::read_only; @@ -1154,6 +1153,21 @@ pub enum TerminatorKind<'tcx> { }, } +/// Information about an assertion failure. +#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)] +pub enum PanicInfo { + BoundsCheck { len: O, index: O }, + Overflow(BinOp), + OverflowNeg, + DivisionByZero, + RemainderByZero, + ResumedAfterReturn(GeneratorKind), + ResumedAfterPanic(GeneratorKind), +} + +/// Type for MIR `Assert` terminator error messages. +pub type AssertMessage<'tcx> = PanicInfo>; + pub type Successors<'a> = iter::Chain, slice::Iter<'a, BasicBlock>>; pub type SuccessorsMut<'a> = @@ -1383,6 +1397,45 @@ impl<'tcx> BasicBlockData<'tcx> { } } +impl PanicInfo { + /// Getting a description does not require `O` to be printable, and does not + /// require allocation. + /// The caller is expected to handle `BoundsCheck` separately. + pub fn description(&self) -> &'static str { + use PanicInfo::*; + match self { + Overflow(BinOp::Add) => "attempt to add with overflow", + Overflow(BinOp::Sub) => "attempt to subtract with overflow", + Overflow(BinOp::Mul) => "attempt to multiply with overflow", + Overflow(BinOp::Div) => "attempt to divide with overflow", + Overflow(BinOp::Rem) => "attempt to calculate the remainder with overflow", + OverflowNeg => "attempt to negate with overflow", + Overflow(BinOp::Shr) => "attempt to shift right with overflow", + Overflow(BinOp::Shl) => "attempt to shift left with overflow", + Overflow(op) => bug!("{:?} cannot overflow", op), + DivisionByZero => "attempt to divide by zero", + RemainderByZero => "attempt to calculate the remainder with a divisor of zero", + ResumedAfterReturn(GeneratorKind::Gen) => "generator resumed after completion", + ResumedAfterReturn(GeneratorKind::Async(_)) => "`async fn` resumed after completion", + ResumedAfterPanic(GeneratorKind::Gen) => "generator resumed after panicking", + ResumedAfterPanic(GeneratorKind::Async(_)) => "`async fn` resumed after panicking", + BoundsCheck { .. } => bug!("Unexpected PanicInfo"), + } + } +} + +impl fmt::Debug for PanicInfo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use PanicInfo::*; + match self { + BoundsCheck { ref len, ref index } => { + write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index) + } + _ => write!(f, "{}", self.description()), + } + } +} + impl<'tcx> Debug for TerminatorKind<'tcx> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { self.fmt_head(fmt)?; diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 555beaa8ca798..529ed71a6f391 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -533,7 +533,7 @@ macro_rules! make_mir_visitor { fn super_assert_message(&mut self, msg: & $($mutability)? AssertMessage<'tcx>, location: Location) { - use crate::mir::interpret::PanicInfo::*; + use crate::mir::PanicInfo::*; match msg { BoundsCheck { len, index } => { self.visit_operand(len, location); diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 0a4610e9e490d..835050fece6db 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -11,7 +11,7 @@ use crate::MemFlags; use rustc::middle::lang_items; use rustc::mir; -use rustc::mir::interpret::PanicInfo; +use rustc::mir::PanicInfo; use rustc::ty::layout::{self, FnAbiExt, HasTyCtxt, LayoutOf}; use rustc::ty::{self, Instance, Ty, TypeFoldable}; use rustc_index::vec::Idx; diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs index 392f164d3148c..317b5edcb410d 100644 --- a/src/librustc_mir/borrow_check/invalidation.rs +++ b/src/librustc_mir/borrow_check/invalidation.rs @@ -153,7 +153,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { } TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => { self.consume_operand(location, cond); - use rustc::mir::interpret::PanicInfo; + use rustc::mir::PanicInfo; if let PanicInfo::BoundsCheck { ref len, ref index } = *msg { self.consume_operand(location, len); self.consume_operand(location, index); diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 88173137bd2e4..899529ce2429a 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -654,7 +654,7 @@ impl<'cx, 'tcx> dataflow::generic::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt } TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => { self.consume_operand(loc, (cond, span), flow_state); - use rustc::mir::interpret::PanicInfo; + use rustc::mir::PanicInfo; if let PanicInfo::BoundsCheck { ref len, ref index } = *msg { self.consume_operand(loc, (len, span), flow_state); self.consume_operand(loc, (index, span), flow_state); diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 100fd7dc48d0e..bb074a81d2a7b 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -9,9 +9,9 @@ use rustc::infer::canonical::QueryRegionConstraints; use rustc::infer::outlives::env::RegionBoundPairs; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin}; -use rustc::mir::interpret::PanicInfo; use rustc::mir::tcx::PlaceTy; use rustc::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; +use rustc::mir::PanicInfo; use rustc::mir::*; use rustc::traits::query::type_op; use rustc::traits::query::type_op::custom::CustomTypeOp; diff --git a/src/librustc_mir/const_eval/error.rs b/src/librustc_mir/const_eval/error.rs index edf0f0a7dbe7c..5f05f439d925a 100644 --- a/src/librustc_mir/const_eval/error.rs +++ b/src/librustc_mir/const_eval/error.rs @@ -1,10 +1,11 @@ use std::error::Error; use std::fmt; +use rustc::mir::PanicInfo; use rustc_span::Symbol; use super::InterpCx; -use crate::interpret::{ConstEvalErr, InterpError, InterpErrorInfo, Machine, PanicInfo}; +use crate::interpret::{ConstEvalErr, InterpError, InterpErrorInfo, Machine}; /// The CTFE machine has some custom error kinds. #[derive(Clone, Debug)] diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index 7fd96ec2d1a5f..65cc53cac9df4 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -8,12 +8,13 @@ use std::hash::Hash; use rustc_data_structures::fx::FxHashMap; +use rustc::mir::AssertMessage; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; use crate::interpret::{ - self, snapshot, AllocId, Allocation, AssertMessage, GlobalId, ImmTy, InterpCx, InterpResult, - Memory, MemoryKind, OpTy, PlaceTy, Pointer, Scalar, + self, snapshot, AllocId, Allocation, GlobalId, ImmTy, InterpCx, InterpResult, Memory, + MemoryKind, OpTy, PlaceTy, Pointer, Scalar, }; use super::error::*; @@ -280,7 +281,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, msg: &AssertMessage<'tcx>, _unwind: Option, ) -> InterpResult<'tcx> { - use rustc::mir::interpret::PanicInfo::*; + use rustc::mir::PanicInfo::*; // Convert `PanicInfo` to `PanicInfo`. let err = match msg { BoundsCheck { ref len, ref index } => { diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 3309e9b9b622a..5291000d10b3f 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -11,8 +11,8 @@ use rustc_hir::def_id::DefId; use rustc_span::Span; use super::{ - AllocId, Allocation, AllocationExtra, AssertMessage, Frame, ImmTy, InterpCx, InterpResult, - Memory, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Scalar, + AllocId, Allocation, AllocationExtra, Frame, ImmTy, InterpCx, InterpResult, Memory, MemoryKind, + OpTy, Operand, PlaceTy, Pointer, Scalar, }; /// Data returned by Machine::stack_pop, @@ -171,7 +171,7 @@ pub trait Machine<'mir, 'tcx>: Sized { fn assert_panic( ecx: &mut InterpCx<'mir, 'tcx, Self>, span: Span, - msg: &AssertMessage<'tcx>, + msg: &mir::AssertMessage<'tcx>, unwind: Option, ) -> InterpResult<'tcx>; diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 5c6c003b3a698..c8d832814c7a5 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -4,13 +4,13 @@ use std::borrow::Cow; use std::cell::Cell; -use rustc::mir::interpret::{InterpError, InterpResult, PanicInfo, Scalar}; +use rustc::mir::interpret::{InterpError, InterpResult, Scalar}; use rustc::mir::visit::{ MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, }; use rustc::mir::{ read_only, AggregateKind, BasicBlock, BinOp, Body, BodyAndCache, ClearCrossCrate, Constant, - Local, LocalDecl, LocalKind, Location, Operand, Place, ReadOnlyBodyAndCache, Rvalue, + Local, LocalDecl, LocalKind, Location, Operand, PanicInfo, Place, ReadOnlyBodyAndCache, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE, }; @@ -198,7 +198,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { fn assert_panic( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _span: Span, - _msg: &rustc::mir::interpret::AssertMessage<'tcx>, + _msg: &rustc::mir::AssertMessage<'tcx>, _unwind: Option, ) -> InterpResult<'tcx> { bug!("panics terminators are not evaluated in ConstProp"); diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index a6fc65731780a..da19fb34927bc 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -1022,7 +1022,7 @@ fn create_generator_resume_function<'tcx>( let mut cases = create_cases(body, &transform, Operation::Resume); - use rustc::mir::interpret::PanicInfo::{ResumedAfterPanic, ResumedAfterReturn}; + use rustc::mir::PanicInfo::{ResumedAfterPanic, ResumedAfterReturn}; // Jump to the entry point on the unresumed cases.insert(0, (UNRESUMED, BasicBlock::new(0))); diff --git a/src/librustc_mir_build/build/expr/as_place.rs b/src/librustc_mir_build/build/expr/as_place.rs index 907300d45aac0..86f87790f2349 100644 --- a/src/librustc_mir_build/build/expr/as_place.rs +++ b/src/librustc_mir_build/build/expr/as_place.rs @@ -5,7 +5,7 @@ use crate::build::ForGuard::{OutsideGuard, RefWithinGuard}; use crate::build::{BlockAnd, BlockAndExtension, Builder}; use crate::hair::*; use rustc::middle::region; -use rustc::mir::interpret::PanicInfo::BoundsCheck; +use rustc::mir::PanicInfo::BoundsCheck; use rustc::mir::*; use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, Variance}; use rustc_span::Span; diff --git a/src/librustc_mir_build/build/expr/as_rvalue.rs b/src/librustc_mir_build/build/expr/as_rvalue.rs index 6f5c5f0dd4c50..5722a8c1cd933 100644 --- a/src/librustc_mir_build/build/expr/as_rvalue.rs +++ b/src/librustc_mir_build/build/expr/as_rvalue.rs @@ -6,7 +6,7 @@ use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, Builder}; use crate::hair::*; use rustc::middle::region; -use rustc::mir::interpret::PanicInfo; +use rustc::mir::PanicInfo; use rustc::mir::*; use rustc::ty::{self, Ty, UpvarSubsts}; use rustc_span::Span; From 55339f2eb7c186334216c35203f98540e8c8cb37 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 11 Feb 2020 11:27:33 +0100 Subject: [PATCH 6/9] small cleanup in ConstEvalErr::struct_generic --- src/librustc/mir/interpret/error.rs | 71 ++++++++++++++++------------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index a7e769b8b9675..64d3269054576 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -126,9 +126,15 @@ impl<'tcx> ConstEvalErr<'tcx> { } } - /// Sets the message passed in via `message` and adds span labels before handing control back - /// to `emit` to do any final processing. It's the caller's responsibility to call emit(), - /// stash(), etc. within the `emit` function to dispose of the diagnostic properly. + /// Create a diagnostic for this const eval error. + /// + /// Sets the message passed in via `message` and adds span labels with detailed error + /// information before handing control back to `emit` to do any final processing. + /// It's the caller's responsibility to call emit(), stash(), etc. within the `emit` + /// function to dispose of the diagnostic properly. + /// + /// If `lint_root.is_some()` report it as a lint, else report it as a hard error. + /// (Except that for some errors, we ignore all that -- see `must_error` below.) fn struct_generic( &self, tcx: TyCtxtAt<'tcx>, @@ -141,6 +147,7 @@ impl<'tcx> ConstEvalErr<'tcx> { return Err(ErrorHandled::TooGeneric); } err_inval!(TypeckError) => return Err(ErrorHandled::Reported), + // We must *always* hard error on these, even if the caller wants just a lint. err_inval!(Layout(LayoutError::SizeOverflow(_))) => true, _ => false, }; @@ -155,10 +162,11 @@ impl<'tcx> ConstEvalErr<'tcx> { err => err.to_string(), }; - let add_span_labels = |err: &mut DiagnosticBuilder<'_>| { - if !must_error { - err.span_label(self.span, err_msg.clone()); + let finish = |mut err: DiagnosticBuilder<'_>, span_msg: Option| { + if let Some(span_msg) = span_msg { + err.span_label(self.span, span_msg); } + // Add spans for the stacktrace. // Skip the last, which is just the environment of the constant. The stacktrace // is sometimes empty because we create "fake" eval contexts in CTFE to do work // on constant values. @@ -167,35 +175,36 @@ impl<'tcx> ConstEvalErr<'tcx> { err.span_label(frame_info.call_site, frame_info.to_string()); } } + // Let the caller finish the job. + emit(err) }; - if let (Some(lint_root), false) = (lint_root, must_error) { - let hir_id = self - .stacktrace - .iter() - .rev() - .filter_map(|frame| frame.lint_root) - .next() - .unwrap_or(lint_root); - tcx.struct_span_lint_hir( - rustc_session::lint::builtin::CONST_ERR, - hir_id, - tcx.span, - |lint| { - let mut err = lint.build(message); - add_span_labels(&mut err); - emit(err); - }, - ); + if must_error { + // The `message` makes little sense here, this is a more serious error than the + // caller thinks anyway. + finish(struct_error(tcx, &err_msg), None); } else { - let mut err = if must_error { - struct_error(tcx, &err_msg) + // Regular case. + if let Some(lint_root) = lint_root { + // Report as lint. + let hir_id = self + .stacktrace + .iter() + .rev() + .filter_map(|frame| frame.lint_root) + .next() + .unwrap_or(lint_root); + tcx.struct_span_lint_hir( + rustc_session::lint::builtin::CONST_ERR, + hir_id, + tcx.span, + |lint| finish(lint.build(message), Some(err_msg)), + ); } else { - struct_error(tcx, message) - }; - add_span_labels(&mut err); - emit(err); - }; + // Report as hard error. + finish(struct_error(tcx, message), Some(err_msg)); + } + } Ok(()) } } From 7e7d1c39edafcbce55ba08449689566e335545b7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 10 Feb 2020 15:58:10 +0100 Subject: [PATCH 7/9] improve comments: - comment for special handling of Shl/Shr - reference a PR --- src/librustc/mir/interpret/error.rs | 1 + src/librustc_mir/transform/const_prop.rs | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 64d3269054576..e747eee30f90d 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -182,6 +182,7 @@ impl<'tcx> ConstEvalErr<'tcx> { if must_error { // The `message` makes little sense here, this is a more serious error than the // caller thinks anyway. + // See . finish(struct_error(tcx, &err_msg), None); } else { // Regular case. diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index c8d832814c7a5..952dede4a1527 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -527,6 +527,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let (_res, overflow, _ty) = this.ecx.overflowing_unary_op(op, val)?; Ok(overflow) })? { + // `AssertKind` only has an `OverflowNeg` variant, to make sure that is + // appropriate to use. assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow"); self.report_panic_as_lint(source_info, PanicInfo::OverflowNeg)?; } @@ -544,6 +546,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { ) -> Option<()> { let r = self.use_ecx(|this| this.ecx.read_immediate(this.ecx.eval_operand(right, None)?))?; + // Check for exceeding shifts *even if* we cannot evaluate the LHS. if op == BinOp::Shr || op == BinOp::Shl { let left_bits = place_layout.size.bits(); let right_size = r.layout.size; @@ -564,7 +567,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } // The remaining operators are handled through `overflowing_binary_op`. - // FIXME: Why do we not also do this for `Shr` and `Shl`? if self.use_ecx(|this| { let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?; let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?; @@ -603,9 +605,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // 2. Working around bugs in other parts of the compiler // - In this case, we'll return `None` from this function to stop evaluation. match rvalue { - // Additional checking: if overflow checks are disabled (which is usually the case in - // release mode), then we need to do additional checking here to give lints to the user - // if an overflow would occur. + // Additional checking: give lints to the user if an overflow would occur. + // If `overflow_check` is set, running const-prop on the `Assert` terminators + // will already generate the appropriate messages. Rvalue::UnaryOp(op, arg) if !overflow_check => { trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg); self.check_unary_op(*op, arg, source_info)?; @@ -613,6 +615,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // Additional checking: check for overflows on integer binary operations and report // them to the user as lints. + // If `overflow_check` is set, running const-prop on the `Assert` terminators + // will already generate the appropriate messages. Rvalue::BinaryOp(op, left, right) if !overflow_check => { trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right); self.check_binary_op(*op, left, right, source_info, place_layout)?; From ed2f22c5a973f4deffa4bd6efbbee0393ff91691 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 12 Feb 2020 19:40:31 +0100 Subject: [PATCH 8/9] rename PanicInfo -> AssertKind --- src/librustc/mir/mod.rs | 18 ++++++++--------- src/librustc/mir/visit.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 6 +++--- src/librustc_mir/borrow_check/invalidation.rs | 4 ++-- src/librustc_mir/borrow_check/mod.rs | 4 ++-- .../borrow_check/type_check/mod.rs | 4 ++-- src/librustc_mir/const_eval/error.rs | 4 ++-- src/librustc_mir/const_eval/machine.rs | 4 ++-- src/librustc_mir/transform/const_prop.rs | 20 +++++++++---------- src/librustc_mir/transform/generator.rs | 2 +- src/librustc_mir_build/build/expr/as_place.rs | 2 +- .../build/expr/as_rvalue.rs | 12 +++++------ 12 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 8d224b6d7394f..4520d3a333316 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1155,7 +1155,7 @@ pub enum TerminatorKind<'tcx> { /// Information about an assertion failure. #[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)] -pub enum PanicInfo { +pub enum AssertKind { BoundsCheck { len: O, index: O }, Overflow(BinOp), OverflowNeg, @@ -1166,7 +1166,7 @@ pub enum PanicInfo { } /// Type for MIR `Assert` terminator error messages. -pub type AssertMessage<'tcx> = PanicInfo>; +pub type AssertMessage<'tcx> = AssertKind>; pub type Successors<'a> = iter::Chain, slice::Iter<'a, BasicBlock>>; @@ -1397,12 +1397,12 @@ impl<'tcx> BasicBlockData<'tcx> { } } -impl PanicInfo { +impl AssertKind { /// Getting a description does not require `O` to be printable, and does not /// require allocation. /// The caller is expected to handle `BoundsCheck` separately. pub fn description(&self) -> &'static str { - use PanicInfo::*; + use AssertKind::*; match self { Overflow(BinOp::Add) => "attempt to add with overflow", Overflow(BinOp::Sub) => "attempt to subtract with overflow", @@ -1419,14 +1419,14 @@ impl PanicInfo { ResumedAfterReturn(GeneratorKind::Async(_)) => "`async fn` resumed after completion", ResumedAfterPanic(GeneratorKind::Gen) => "generator resumed after panicking", ResumedAfterPanic(GeneratorKind::Async(_)) => "`async fn` resumed after panicking", - BoundsCheck { .. } => bug!("Unexpected PanicInfo"), + BoundsCheck { .. } => bug!("Unexpected AssertKind"), } } } -impl fmt::Debug for PanicInfo { +impl fmt::Debug for AssertKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use PanicInfo::*; + use AssertKind::*; match self { BoundsCheck { ref len, ref index } => { write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index) @@ -2719,7 +2719,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { } } Assert { ref cond, expected, ref msg, target, cleanup } => { - use PanicInfo::*; + use AssertKind::*; let msg = match msg { BoundsCheck { ref len, ref index } => { BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) } @@ -2768,7 +2768,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { } Assert { ref cond, ref msg, .. } => { if cond.visit_with(visitor) { - use PanicInfo::*; + use AssertKind::*; match msg { BoundsCheck { ref len, ref index } => { len.visit_with(visitor) || index.visit_with(visitor) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 529ed71a6f391..8330bbe083432 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -533,7 +533,7 @@ macro_rules! make_mir_visitor { fn super_assert_message(&mut self, msg: & $($mutability)? AssertMessage<'tcx>, location: Location) { - use crate::mir::PanicInfo::*; + use crate::mir::AssertKind::*; match msg { BoundsCheck { len, index } => { self.visit_operand(len, location); diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 835050fece6db..916c15eb1b6ea 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -11,7 +11,7 @@ use crate::MemFlags; use rustc::middle::lang_items; use rustc::mir; -use rustc::mir::PanicInfo; +use rustc::mir::AssertKind; use rustc::ty::layout::{self, FnAbiExt, HasTyCtxt, LayoutOf}; use rustc::ty::{self, Instance, Ty, TypeFoldable}; use rustc_index::vec::Idx; @@ -378,7 +378,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // checked operation, just a comparison with the minimum // value, so we have to check for the assert message. if !bx.check_overflow() { - if let PanicInfo::OverflowNeg = *msg { + if let AssertKind::OverflowNeg = *msg { const_cond = Some(expected); } } @@ -412,7 +412,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Put together the arguments to the panic entry point. let (lang_item, args) = match msg { - PanicInfo::BoundsCheck { ref len, ref index } => { + AssertKind::BoundsCheck { ref len, ref index } => { let len = self.codegen_operand(&mut bx, len).immediate(); let index = self.codegen_operand(&mut bx, index).immediate(); (lang_items::PanicBoundsCheckFnLangItem, vec![location, index, len]) diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs index 317b5edcb410d..0bead27050ce6 100644 --- a/src/librustc_mir/borrow_check/invalidation.rs +++ b/src/librustc_mir/borrow_check/invalidation.rs @@ -153,8 +153,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { } TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => { self.consume_operand(location, cond); - use rustc::mir::PanicInfo; - if let PanicInfo::BoundsCheck { ref len, ref index } = *msg { + use rustc::mir::AssertKind; + if let AssertKind::BoundsCheck { ref len, ref index } = *msg { self.consume_operand(location, len); self.consume_operand(location, index); } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 899529ce2429a..941534e68fcad 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -654,8 +654,8 @@ impl<'cx, 'tcx> dataflow::generic::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt } TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => { self.consume_operand(loc, (cond, span), flow_state); - use rustc::mir::PanicInfo; - if let PanicInfo::BoundsCheck { ref len, ref index } = *msg { + use rustc::mir::AssertKind; + if let AssertKind::BoundsCheck { ref len, ref index } = *msg { self.consume_operand(loc, (len, span), flow_state); self.consume_operand(loc, (index, span), flow_state); } diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index bb074a81d2a7b..5f7bf148e331d 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -11,7 +11,7 @@ use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin}; use rustc::mir::tcx::PlaceTy; use rustc::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; -use rustc::mir::PanicInfo; +use rustc::mir::AssertKind; use rustc::mir::*; use rustc::traits::query::type_op; use rustc::traits::query::type_op::custom::CustomTypeOp; @@ -1563,7 +1563,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty); } - if let PanicInfo::BoundsCheck { ref len, ref index } = *msg { + if let AssertKind::BoundsCheck { ref len, ref index } = *msg { if len.ty(body, tcx) != tcx.types.usize { span_mirbug!(self, len, "bounds-check length non-usize {:?}", len) } diff --git a/src/librustc_mir/const_eval/error.rs b/src/librustc_mir/const_eval/error.rs index 5f05f439d925a..63ad9ec8cae9e 100644 --- a/src/librustc_mir/const_eval/error.rs +++ b/src/librustc_mir/const_eval/error.rs @@ -1,7 +1,7 @@ use std::error::Error; use std::fmt; -use rustc::mir::PanicInfo; +use rustc::mir::AssertKind; use rustc_span::Symbol; use super::InterpCx; @@ -12,7 +12,7 @@ use crate::interpret::{ConstEvalErr, InterpError, InterpErrorInfo, Machine}; pub enum ConstEvalErrKind { NeedsRfc(String), ConstAccessesStatic, - AssertFailure(PanicInfo), + AssertFailure(AssertKind), Panic { msg: Symbol, line: u32, col: u32, file: Symbol }, } diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index 65cc53cac9df4..e40436ccf0b4b 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -281,8 +281,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, msg: &AssertMessage<'tcx>, _unwind: Option, ) -> InterpResult<'tcx> { - use rustc::mir::PanicInfo::*; - // Convert `PanicInfo` to `PanicInfo`. + use rustc::mir::AssertKind::*; + // Convert `AssertKind` to `AssertKind`. let err = match msg { BoundsCheck { ref len, ref index } => { let len = ecx diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 952dede4a1527..09eb6e952add6 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -9,8 +9,8 @@ use rustc::mir::visit::{ MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, }; use rustc::mir::{ - read_only, AggregateKind, BasicBlock, BinOp, Body, BodyAndCache, ClearCrossCrate, Constant, - Local, LocalDecl, LocalKind, Location, Operand, PanicInfo, Place, ReadOnlyBodyAndCache, Rvalue, + read_only, AggregateKind, AssertKind, BasicBlock, BinOp, Body, BodyAndCache, ClearCrossCrate, + Constant, Local, LocalDecl, LocalKind, Location, Operand, Place, ReadOnlyBodyAndCache, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE, }; @@ -501,7 +501,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - fn report_panic_as_lint(&self, source_info: SourceInfo, panic: PanicInfo) -> Option<()> { + fn report_panic_as_lint(&self, source_info: SourceInfo, panic: AssertKind) -> Option<()> { // Somewhat convoluted way to re-use the CTFE error reporting code. let lint_root = self.lint_root(source_info)?; let error = InterpError::MachineStop(Box::new(format!("{:?}", panic))); @@ -530,7 +530,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // `AssertKind` only has an `OverflowNeg` variant, to make sure that is // appropriate to use. assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow"); - self.report_panic_as_lint(source_info, PanicInfo::OverflowNeg)?; + self.report_panic_as_lint(source_info, AssertKind::OverflowNeg)?; } Some(()) @@ -572,7 +572,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?; Ok(overflow) })? { - self.report_panic_as_lint(source_info, PanicInfo::Overflow(op))?; + self.report_panic_as_lint(source_info, AssertKind::Overflow(op))?; } Some(()) @@ -910,11 +910,11 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { span, |lint| { let msg = match msg { - PanicInfo::Overflow(_) - | PanicInfo::OverflowNeg - | PanicInfo::DivisionByZero - | PanicInfo::RemainderByZero => msg.description().to_owned(), - PanicInfo::BoundsCheck { ref len, ref index } => { + AssertKind::Overflow(_) + | AssertKind::OverflowNeg + | AssertKind::DivisionByZero + | AssertKind::RemainderByZero => msg.description().to_owned(), + AssertKind::BoundsCheck { ref len, ref index } => { let len = self .eval_operand(len, source_info) .expect("len must be const"); diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index da19fb34927bc..d5d9a8c83cd37 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -1022,7 +1022,7 @@ fn create_generator_resume_function<'tcx>( let mut cases = create_cases(body, &transform, Operation::Resume); - use rustc::mir::PanicInfo::{ResumedAfterPanic, ResumedAfterReturn}; + use rustc::mir::AssertKind::{ResumedAfterPanic, ResumedAfterReturn}; // Jump to the entry point on the unresumed cases.insert(0, (UNRESUMED, BasicBlock::new(0))); diff --git a/src/librustc_mir_build/build/expr/as_place.rs b/src/librustc_mir_build/build/expr/as_place.rs index 86f87790f2349..d77cc49c94f67 100644 --- a/src/librustc_mir_build/build/expr/as_place.rs +++ b/src/librustc_mir_build/build/expr/as_place.rs @@ -5,7 +5,7 @@ use crate::build::ForGuard::{OutsideGuard, RefWithinGuard}; use crate::build::{BlockAnd, BlockAndExtension, Builder}; use crate::hair::*; use rustc::middle::region; -use rustc::mir::PanicInfo::BoundsCheck; +use rustc::mir::AssertKind::BoundsCheck; use rustc::mir::*; use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, Variance}; use rustc_span::Span; diff --git a/src/librustc_mir_build/build/expr/as_rvalue.rs b/src/librustc_mir_build/build/expr/as_rvalue.rs index 5722a8c1cd933..dc97f321a36ad 100644 --- a/src/librustc_mir_build/build/expr/as_rvalue.rs +++ b/src/librustc_mir_build/build/expr/as_rvalue.rs @@ -6,7 +6,7 @@ use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, Builder}; use crate::hair::*; use rustc::middle::region; -use rustc::mir::PanicInfo; +use rustc::mir::AssertKind; use rustc::mir::*; use rustc::ty::{self, Ty, UpvarSubsts}; use rustc_span::Span; @@ -86,7 +86,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, Operand::Move(is_min), false, - PanicInfo::OverflowNeg, + AssertKind::OverflowNeg, expr_span, ); } @@ -294,7 +294,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let val = tcx.mk_place_field(result_value.clone(), val_fld, ty); let of = tcx.mk_place_field(result_value, of_fld, bool_ty); - let err = PanicInfo::Overflow(op); + let err = AssertKind::Overflow(op); block = self.assert(block, Operand::Move(of), false, err, span); @@ -305,11 +305,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // and 2. there are two possible failure cases, divide-by-zero and overflow. let zero_err = if op == BinOp::Div { - PanicInfo::DivisionByZero + AssertKind::DivisionByZero } else { - PanicInfo::RemainderByZero + AssertKind::RemainderByZero }; - let overflow_err = PanicInfo::Overflow(op); + let overflow_err = AssertKind::Overflow(op); // Check for / 0 let is_zero = self.temp(bool_ty, span); From 33ba83c3a0905c86a6b5182b3b3d35f2f6086e5b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 13 Feb 2020 11:26:09 +0100 Subject: [PATCH 9/9] fix typo --- src/librustc_mir/transform/const_prop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 09eb6e952add6..5729cda64f7ae 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -527,7 +527,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let (_res, overflow, _ty) = this.ecx.overflowing_unary_op(op, val)?; Ok(overflow) })? { - // `AssertKind` only has an `OverflowNeg` variant, to make sure that is + // `AssertKind` only has an `OverflowNeg` variant, so make sure that is // appropriate to use. assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow"); self.report_panic_as_lint(source_info, AssertKind::OverflowNeg)?;