code review fixes

This commit is contained in:
Saleem Jaffer 2019-07-31 12:48:54 +05:30
parent 5585445a33
commit 152f0d347e
13 changed files with 105 additions and 109 deletions

View file

@ -137,13 +137,12 @@ impl<'tcx> ConstEvalErr<'tcx> {
message: &str,
lint_root: Option<hir::HirId>,
) -> Result<DiagnosticBuilder<'tcx>, ErrorHandled> {
use InvalidProgramInfo::*;
match self.error {
InterpError::InvalidProgram(Layout(LayoutError::Unknown(_))) |
InterpError::InvalidProgram(TooGeneric) =>
err_inval!(Layout(LayoutError::Unknown(_))) |
err_inval!(TooGeneric) =>
return Err(ErrorHandled::TooGeneric),
InterpError::InvalidProgram(Layout(LayoutError::SizeOverflow(_))) |
InterpError::InvalidProgram(TypeckError) =>
err_inval!(Layout(LayoutError::SizeOverflow(_))) |
err_inval!(TypeckError) =>
return Err(ErrorHandled::Reported),
_ => {},
}
@ -549,7 +548,9 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
pub enum ResourceExhaustionInfo {
/// The stack grew too big.
StackFrameLimitReached,
/// The program ran into an infinite loop.
InfiniteLoop,
}

View file

@ -21,20 +21,12 @@ macro_rules! throw_ub {
#[macro_export]
macro_rules! throw_panic {
($($tt:tt)*) => {
return Err($crate::mir::interpret::InterpError::Panic(
$crate::mir::interpret::PanicInfo::$($tt)*
).into())
};
($($tt:tt)*) => { return Err(err_panic!($($tt)*).into()) };
}
#[macro_export]
macro_rules! throw_exhaust {
($($tt:tt)*) => {
return Err($crate::mir::interpret::InterpError::ResourceExhaustion(
$crate::mir::interpret::ResourceExhaustionInfo::$($tt)*
).into())
};
($($tt:tt)*) => { return Err(err_exhaust!($($tt)*).into()) };
}
#[macro_export]
@ -55,6 +47,24 @@ macro_rules! err_unsup {
};
}
#[macro_export]
macro_rules! err_exhaust {
($($tt:tt)*) => {
$crate::mir::interpret::InterpError::ResourceExhaustion(
$crate::mir::interpret::ResourceExhaustionInfo::$($tt)*
)
};
}
#[macro_export]
macro_rules! err_panic {
($($tt:tt)*) => {
$crate::mir::interpret::InterpError::Panic(
$crate::mir::interpret::PanicInfo::$($tt)*
)
};
}
mod error;
mod value;
mod allocation;

View file

@ -22,9 +22,9 @@ use syntax::source_map::{Span, DUMMY_SP};
use crate::interpret::{self,
PlaceTy, MPlaceTy, OpTy, ImmTy, Immediate, Scalar,
RawConst, ConstValue,
InterpResult, InterpErrorInfo, InterpError, GlobalId, InterpCx, StackPopCleanup,
InterpResult, InterpErrorInfo, GlobalId, InterpCx, StackPopCleanup,
Allocation, AllocId, MemoryKind,
snapshot, RefTracking, intern_const_alloc_recursive, UnsupportedOpInfo,
snapshot, RefTracking, intern_const_alloc_recursive,
};
/// Number of steps until the detector even starts doing anything.
@ -183,7 +183,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalError {
fn into(self) -> InterpErrorInfo<'tcx> {
InterpError::Unsupported(UnsupportedOpInfo::MachineError(self.to_string())).into()
err_unsup!(MachineError(self.to_string())).into()
}
}
@ -360,7 +360,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
Ok(Some(match ecx.load_mir(instance.def) {
Ok(body) => body,
Err(err) => {
if let InterpError::Unsupported(UnsupportedOpInfo::NoMirFor(ref path)) = err.kind {
if let err_unsup!(NoMirFor(ref path)) = err.kind {
return Err(
ConstEvalError::NeedsRfc(format!("calling extern function `{}`", path))
.into(),
@ -697,9 +697,8 @@ pub fn const_eval_raw_provider<'tcx>(
// promoting runtime code is only allowed to error if it references broken constants
// any other kind of error will be reported to the user as a deny-by-default lint
_ => if let Some(p) = cid.promoted {
use crate::interpret::InvalidProgramInfo::ReferencedConstant;
let span = tcx.promoted_mir(def_id)[p].span;
if let InterpError::InvalidProgram(ReferencedConstant) = err.error {
if let err_inval!(ReferencedConstant) = err.error {
err.report_as_error(
tcx.at(span),
"evaluation of constant expression failed",

View file

@ -16,8 +16,7 @@ use rustc_data_structures::indexed_vec::IndexVec;
use rustc::mir::interpret::{
ErrorHandled,
GlobalId, Scalar, Pointer, FrameInfo, AllocId,
InterpResult, InterpError,
truncate, sign_extend, InvalidProgramInfo,
InterpResult, truncate, sign_extend,
};
use rustc_data_structures::fx::FxHashMap;
@ -193,7 +192,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx, M> {
self.tcx
.layout_of(self.param_env.and(ty))
.map_err(|layout| {
InterpError::InvalidProgram(InvalidProgramInfo::Layout(layout)).into()
err_inval!(Layout(layout)).into()
})
}
}
@ -698,9 +697,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let val = self.tcx.const_eval_raw(param_env.and(gid)).map_err(|err| {
match err {
ErrorHandled::Reported =>
InterpError::InvalidProgram(InvalidProgramInfo::ReferencedConstant),
err_inval!(ReferencedConstant),
ErrorHandled::TooGeneric =>
InterpError::InvalidProgram(InvalidProgramInfo::TooGeneric),
err_inval!(TooGeneric),
}
})?;
self.raw_const_to_mplace(val)

View file

@ -4,9 +4,7 @@
//! memory, we need to extract all memory allocations to the global memory pool so they stay around.
use rustc::ty::{Ty, TyCtxt, ParamEnv, self};
use rustc::mir::interpret::{
InterpResult, ErrorHandled, UnsupportedOpInfo,
};
use rustc::mir::interpret::{InterpResult, ErrorHandled};
use rustc::hir;
use rustc::hir::def_id::DefId;
use super::validity::RefTracking;
@ -16,7 +14,7 @@ use syntax::ast::Mutability;
use syntax_pos::Span;
use super::{
ValueVisitor, MemoryKind, Pointer, AllocId, MPlaceTy, InterpError, Scalar,
ValueVisitor, MemoryKind, Pointer, AllocId, MPlaceTy, Scalar,
};
use crate::const_eval::{CompileTimeInterpreter, CompileTimeEvalContext};
@ -293,7 +291,7 @@ pub fn intern_const_alloc_recursive(
if let Err(error) = interned {
// This can happen when e.g. the tag of an enum is not a valid discriminant. We do have
// to read enum discriminants in order to find references in enum variant fields.
if let InterpError::Unsupported(UnsupportedOpInfo::ValidationFailure(_)) = error.kind {
if let err_unsup!(ValidationFailure(_)) = error.kind {
let err = crate::const_eval::error_to_const_error(&ecx, error);
match err.struct_error(ecx.tcx, "it is undefined behavior to use this value") {
Ok(mut diag) => {

View file

@ -6,9 +6,7 @@ use syntax::symbol::Symbol;
use rustc::ty;
use rustc::ty::layout::{LayoutOf, Primitive, Size};
use rustc::mir::BinOp;
use rustc::mir::interpret::{
InterpResult, InterpError, Scalar, PanicInfo, UnsupportedOpInfo,
};
use rustc::mir::interpret::{InterpResult, Scalar};
use super::{
Machine, PlaceTy, OpTy, InterpCx, Immediate,
@ -100,7 +98,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let bits = self.read_scalar(args[0])?.to_bits(layout_of.size)?;
let kind = match layout_of.abi {
ty::layout::Abi::Scalar(ref scalar) => scalar.value,
_ => Err(InterpError::Unsupported(UnsupportedOpInfo::TypeNotPrimitive(ty)))?,
_ => Err(err_unsup!(TypeNotPrimitive(ty)))?,
};
let out_val = if intrinsic_name.ends_with("_nonzero") {
if bits == 0 {
@ -250,7 +248,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let file = Symbol::intern(self.read_str(file_place)?);
let line = self.read_scalar(line.into())?.to_u32()?;
let col = self.read_scalar(col.into())?.to_u32()?;
return Err(InterpError::Panic(PanicInfo::Panic { msg, file, line, col }).into());
throw_panic!(Panic { msg, file, line, col })
} else if Some(def_id) == self.tcx.lang_items().begin_panic_fn() {
assert!(args.len() == 2);
// &'static str, &(&'static str, u32, u32)
@ -268,7 +266,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let file = Symbol::intern(self.read_str(file_place)?);
let line = self.read_scalar(line.into())?.to_u32()?;
let col = self.read_scalar(col.into())?.to_u32()?;
return Err(InterpError::Panic(PanicInfo::Panic { msg, file, line, col }).into());
throw_panic!(Panic { msg, file, line, col })
} else {
return Ok(false);
}

View file

@ -10,8 +10,8 @@ use rustc::mir;
use rustc::ty::{self, TyCtxt};
use super::{
Allocation, AllocId, InterpResult, InterpError, Scalar, AllocationExtra,
InterpCx, PlaceTy, OpTy, ImmTy, MemoryKind, Pointer, Memory, UnsupportedOpInfo,
Allocation, AllocId, InterpResult, Scalar, AllocationExtra,
InterpCx, PlaceTy, OpTy, ImmTy, MemoryKind, Pointer, Memory,
};
/// Whether this kind of memory is allowed to leak
@ -240,9 +240,9 @@ pub trait Machine<'mir, 'tcx>: Sized {
int: u64,
) -> InterpResult<'tcx, Pointer<Self::PointerTag>> {
Err((if int == 0 {
InterpError::Unsupported(UnsupportedOpInfo::InvalidNullPointerUsage)
err_unsup!(InvalidNullPointerUsage)
} else {
InterpError::Unsupported(UnsupportedOpInfo::ReadBytesAsPointer)
err_unsup!(ReadBytesAsPointer)
}).into())
}

View file

@ -18,8 +18,8 @@ use syntax::ast::Mutability;
use super::{
Pointer, AllocId, Allocation, GlobalId, AllocationExtra,
InterpResult, Scalar, InterpError, GlobalAlloc, PointerArithmetic,
Machine, AllocMap, MayLeak, ErrorHandled, CheckInAllocMsg, InvalidProgramInfo,
InterpResult, Scalar, GlobalAlloc, PointerArithmetic,
Machine, AllocMap, MayLeak, ErrorHandled, CheckInAllocMsg,
};
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
@ -250,18 +250,17 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
Some(alloc) => alloc,
None => {
// Deallocating static memory -- always an error
match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
Some(GlobalAlloc::Function(..)) => throw_unsup!(DeallocatedWrongMemoryKind(
return Err(match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
Some(GlobalAlloc::Function(..)) => err_unsup!(DeallocatedWrongMemoryKind(
"function".to_string(),
format!("{:?}", kind),
)),
Some(GlobalAlloc::Static(..)) |
Some(GlobalAlloc::Memory(..)) => throw_unsup!(DeallocatedWrongMemoryKind(
"static".to_string(),
format!("{:?}", kind),
)),
None => throw_unsup!(DoubleFree)
Some(GlobalAlloc::Static(..)) | Some(GlobalAlloc::Memory(..)) => err_unsup!(
DeallocatedWrongMemoryKind("static".to_string(), format!("{:?}", kind))
),
None => err_unsup!(DoubleFree),
}
.into());
}
};
@ -437,11 +436,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
assert!(tcx.is_static(def_id));
match err {
ErrorHandled::Reported =>
InterpError::InvalidProgram(
InvalidProgramInfo::ReferencedConstant
),
err_inval!(ReferencedConstant),
ErrorHandled::TooGeneric =>
InterpError::InvalidProgram(InvalidProgramInfo::TooGeneric),
err_inval!(TooGeneric),
}
})?;
// Make sure we use the ID of the resolved memory, not the lazy one!

View file

@ -11,8 +11,7 @@ use rustc::ty::layout::{
use rustc::mir::interpret::{
GlobalId, AllocId,
ConstValue, Pointer, Scalar,
InterpResult, InterpError,
sign_extend, truncate, UnsupportedOpInfo,
InterpResult, sign_extend, truncate,
};
use super::{
InterpCx, Machine,
@ -332,7 +331,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let len = mplace.len(self)?;
let bytes = self.memory.read_bytes(mplace.ptr, Size::from_bytes(len as u64))?;
let str = ::std::str::from_utf8(bytes).map_err(|err| {
InterpError::Unsupported(UnsupportedOpInfo::ValidationFailure(err.to_string()))
err_unsup!(ValidationFailure(err.to_string()))
})?;
Ok(str)
}
@ -604,7 +603,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let raw_discr = discr_val.to_scalar_or_undef();
trace!("discr value: {:?}", raw_discr);
// post-process
use rustc::mir::interpret::UnsupportedOpInfo::InvalidDiscriminant;
Ok(match *discr_kind {
layout::DiscriminantKind::Tag => {
let bits_discr = match raw_discr.to_bits(discr_val.layout.size) {
@ -649,7 +647,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let variants_start = niche_variants.start().as_u32() as u128;
let variants_end = niche_variants.end().as_u32() as u128;
let raw_discr = raw_discr.not_undef().map_err(|_| {
InterpError::Unsupported(InvalidDiscriminant(ScalarMaybeUndef::Undef))
err_unsup!(InvalidDiscriminant(ScalarMaybeUndef::Undef))
})?;
match raw_discr.to_bits_or_ptr(discr_val.layout.size, self) {
Err(ptr) => {

View file

@ -11,8 +11,7 @@ use rustc::ich::StableHashingContextProvider;
use rustc::mir;
use rustc::mir::interpret::{
AllocId, Pointer, Scalar,
Relocations, Allocation, UndefMask,
InterpResult, InterpError, ResourceExhaustionInfo,
Relocations, Allocation, UndefMask, InterpResult,
};
use rustc::ty::{self, TyCtxt};
@ -77,7 +76,7 @@ impl<'mir, 'tcx> InfiniteLoopDetector<'mir, 'tcx> {
}
// Second cycle
Err(InterpError::ResourceExhaustion(ResourceExhaustionInfo::InfiniteLoop).into())
throw_exhaust!(InfiniteLoop)
}
}

View file

@ -136,31 +136,29 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} else {
// Compute error message
use rustc::mir::interpret::PanicInfo::*;
match msg {
return Err(match msg {
BoundsCheck { ref len, ref index } => {
let len = self.read_immediate(self.eval_operand(len, None)?)
.expect("can't eval len").to_scalar()?
let len = self
.read_immediate(self.eval_operand(len, None)?)
.expect("can't eval len")
.to_scalar()?
.to_bits(self.memory().pointer_size())? as u64;
let index = self.read_immediate(self.eval_operand(index, None)?)
.expect("can't eval index").to_scalar()?
let index = self
.read_immediate(self.eval_operand(index, None)?)
.expect("can't eval index")
.to_scalar()?
.to_bits(self.memory().pointer_size())? as u64;
throw_panic!(BoundsCheck { len, index })
err_panic!(BoundsCheck { len, index })
}
Overflow(op) =>
throw_panic!(Overflow(*op)),
OverflowNeg =>
throw_panic!(OverflowNeg),
DivisionByZero =>
throw_panic!(DivisionByZero),
RemainderByZero =>
throw_panic!(RemainderByZero),
GeneratorResumedAfterReturn =>
throw_panic!(GeneratorResumedAfterReturn),
GeneratorResumedAfterPanic =>
throw_panic!(GeneratorResumedAfterPanic),
Panic { .. } =>
bug!("`Panic` variant cannot occur in MIR"),
};
Overflow(op) => err_panic!(Overflow(*op)),
OverflowNeg => err_panic!(OverflowNeg),
DivisionByZero => err_panic!(DivisionByZero),
RemainderByZero => err_panic!(RemainderByZero),
GeneratorResumedAfterReturn => err_panic!(GeneratorResumedAfterReturn),
GeneratorResumedAfterPanic => err_panic!(GeneratorResumedAfterPanic),
Panic { .. } => bug!("`Panic` variant cannot occur in MIR"),
}
.into());
}
}

View file

@ -10,11 +10,11 @@ use rustc_data_structures::fx::FxHashSet;
use std::hash::Hash;
use super::{
GlobalAlloc, InterpResult, InterpError,
OpTy, Machine, InterpCx, ValueVisitor, MPlaceTy, UnsupportedOpInfo,
GlobalAlloc, InterpResult,
OpTy, Machine, InterpCx, ValueVisitor, MPlaceTy,
};
macro_rules! validation_failure {
macro_rules! throw_validation_failure {
($what:expr, $where:expr, $details:expr) => {{
let where_ = path_format(&$where);
let where_ = if where_.is_empty() {
@ -45,14 +45,14 @@ macro_rules! try_validation {
($e:expr, $what:expr, $where:expr, $details:expr) => {{
match $e {
Ok(x) => x,
Err(_) => validation_failure!($what, $where, $details),
Err(_) => throw_validation_failure!($what, $where, $details),
}
}};
($e:expr, $what:expr, $where:expr) => {{
match $e {
Ok(x) => x,
Err(_) => validation_failure!($what, $where),
Err(_) => throw_validation_failure!($what, $where),
}
}}
}
@ -297,12 +297,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
match self.walk_value(op) {
Ok(()) => Ok(()),
Err(err) => match err.kind {
InterpError::Unsupported(UnsupportedOpInfo::InvalidDiscriminant(val)) =>
validation_failure!(
err_unsup!(InvalidDiscriminant(val)) =>
throw_validation_failure!(
val, self.path, "a valid enum discriminant"
),
InterpError::Unsupported(UnsupportedOpInfo::ReadPointerAsBytes) =>
validation_failure!(
err_unsup!(ReadPointerAsBytes) =>
throw_validation_failure!(
"a pointer", self.path, "plain (non-pointer) bytes"
),
_ => Err(err),
@ -405,21 +405,20 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
"{:?} did not pass access check for size {:?}, align {:?}",
ptr, size, align
);
use super::UnsupportedOpInfo::*;
match err.kind {
InterpError::Unsupported(InvalidNullPointerUsage) =>
validation_failure!("NULL reference", self.path),
InterpError::Unsupported(AlignmentCheckFailed { required, has }) =>
validation_failure!(format!("unaligned reference \
err_unsup!(InvalidNullPointerUsage) =>
throw_validation_failure!("NULL reference", self.path),
err_unsup!(AlignmentCheckFailed { required, has }) =>
throw_validation_failure!(format!("unaligned reference \
(required {} byte alignment but found {})",
required.bytes(), has.bytes()), self.path),
InterpError::Unsupported(ReadBytesAsPointer) =>
validation_failure!(
err_unsup!(ReadBytesAsPointer) =>
throw_validation_failure!(
"dangling reference (created from integer)",
self.path
),
_ =>
validation_failure!(
throw_validation_failure!(
"dangling reference (not entirely in bounds)",
self.path
),
@ -479,7 +478,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
fn visit_uninhabited(&mut self) -> InterpResult<'tcx>
{
validation_failure!("a value of an uninhabited type", self.path)
throw_validation_failure!("a value of an uninhabited type", self.path)
}
fn visit_scalar(
@ -512,7 +511,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
if lo == 1 && hi == max_hi {
// Only NULL is the niche. So make sure the ptr is NOT NULL.
if self.ecx.memory.ptr_may_be_null(ptr) {
validation_failure!(
throw_validation_failure!(
"a potentially NULL pointer",
self.path,
format!(
@ -525,7 +524,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
} else {
// Conservatively, we reject, because the pointer *could* have a bad
// value.
validation_failure!(
throw_validation_failure!(
"a pointer",
self.path,
format!(
@ -542,7 +541,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
if wrapping_range_contains(&layout.valid_range, bits) {
Ok(())
} else {
validation_failure!(
throw_validation_failure!(
bits,
self.path,
format!("something {}", wrapping_range_format(&layout.valid_range, max_hi))
@ -609,14 +608,14 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
Err(err) => {
// For some errors we might be able to provide extra information
match err.kind {
InterpError::Unsupported(UnsupportedOpInfo::ReadUndefBytes(offset)) => {
err_unsup!(ReadUndefBytes(offset)) => {
// Some byte was undefined, determine which
// element that byte belongs to so we can
// provide an index.
let i = (offset.bytes() / ty_size.bytes()) as usize;
self.path.push(PathElem::ArrayElem(i));
validation_failure!("undefined bytes", self.path)
throw_validation_failure!("undefined bytes", self.path)
},
// Other errors shouldn't be possible
_ => return Err(err),

View file

@ -13,7 +13,7 @@ use rustc::mir::{
use rustc::mir::visit::{
Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext,
};
use rustc::mir::interpret::{Scalar, GlobalId, InterpResult, InterpError, PanicInfo};
use rustc::mir::interpret::{Scalar, GlobalId, InterpResult, PanicInfo};
use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
use syntax_pos::{Span, DUMMY_SP};
use rustc::ty::subst::InternalSubsts;
@ -519,7 +519,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
)
} else {
if overflow {
let err = InterpError::Panic(PanicInfo::Overflow(op)).into();
let err = err_panic!(Overflow(op)).into();
let _: Option<()> = self.use_ecx(source_info, |_| Err(err));
return None;
}