Skip to content

Commit 0633a0e

Browse files
committed
remove Panic variant from InterpError
1 parent 2e6eace commit 0633a0e

File tree

7 files changed

+117
-123
lines changed

7 files changed

+117
-123
lines changed

src/librustc/mir/interpret/error.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ impl<'tcx> ConstEvalErr<'tcx> {
139139
lint_root: Option<hir::HirId>,
140140
) -> Result<(), ErrorHandled> {
141141
let must_error = match self.error {
142-
InterpError::MachineStop(_) => bug!("CTFE does not stop"),
143142
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
144143
return Err(ErrorHandled::TooGeneric);
145144
}
@@ -149,9 +148,18 @@ impl<'tcx> ConstEvalErr<'tcx> {
149148
};
150149
trace!("reporting const eval failure at {:?}", self.span);
151150

151+
let err_msg = match &self.error {
152+
InterpError::MachineStop(msg) => {
153+
// A custom error (`ConstEvalErrKind` in `librustc_mir/interp/const_eval/error.rs`).
154+
// Should be turned into a string by now.
155+
msg.downcast_ref::<String>().expect("invalid MachineStop payload").clone()
156+
}
157+
err => err.to_string(),
158+
};
159+
152160
let add_span_labels = |err: &mut DiagnosticBuilder<'_>| {
153161
if !must_error {
154-
err.span_label(self.span, self.error.to_string());
162+
err.span_label(self.span, err_msg.clone());
155163
}
156164
// Skip the last, which is just the environment of the constant. The stacktrace
157165
// is sometimes empty because we create "fake" eval contexts in CTFE to do work
@@ -183,7 +191,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
183191
);
184192
} else {
185193
let mut err = if must_error {
186-
struct_error(tcx, &self.error.to_string())
194+
struct_error(tcx, &err_msg)
187195
} else {
188196
struct_error(tcx, message)
189197
};
@@ -259,6 +267,9 @@ impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
259267
}
260268
}
261269

270+
/// Information about a panic.
271+
///
272+
/// FIXME: this is not actually an InterpError, and should probably be moved to another module.
262273
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
263274
pub enum PanicInfo<O> {
264275
Panic { msg: Symbol, line: u32, col: u32, file: Symbol },
@@ -616,8 +627,6 @@ impl fmt::Debug for ResourceExhaustionInfo {
616627
}
617628

618629
pub enum InterpError<'tcx> {
619-
/// The program panicked.
620-
Panic(PanicInfo<u64>),
621630
/// The program caused undefined behavior.
622631
UndefinedBehavior(UndefinedBehaviorInfo),
623632
/// The program did something the interpreter does not support (some of these *might* be UB
@@ -650,8 +659,7 @@ impl fmt::Debug for InterpError<'_> {
650659
InvalidProgram(ref msg) => write!(f, "{:?}", msg),
651660
UndefinedBehavior(ref msg) => write!(f, "{:?}", msg),
652661
ResourceExhaustion(ref msg) => write!(f, "{:?}", msg),
653-
Panic(ref msg) => write!(f, "{:?}", msg),
654-
MachineStop(_) => write!(f, "machine caused execution to stop"),
662+
MachineStop(_) => bug!("unhandled MachineStop"),
655663
}
656664
}
657665
}

src/librustc/mir/interpret/mod.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,6 @@ macro_rules! err_ub_format {
3737
($($tt:tt)*) => { err_ub!(Ub(format!($($tt)*))) };
3838
}
3939

40-
#[macro_export]
41-
macro_rules! err_panic {
42-
($($tt:tt)*) => {
43-
$crate::mir::interpret::InterpError::Panic(
44-
$crate::mir::interpret::PanicInfo::$($tt)*
45-
)
46-
};
47-
}
48-
4940
#[macro_export]
5041
macro_rules! err_exhaust {
5142
($($tt:tt)*) => {
@@ -80,11 +71,6 @@ macro_rules! throw_ub_format {
8071
($($tt:tt)*) => { throw_ub!(Ub(format!($($tt)*))) };
8172
}
8273

83-
#[macro_export]
84-
macro_rules! throw_panic {
85-
($($tt:tt)*) => { return Err(err_panic!($($tt)*).into()) };
86-
}
87-
8874
#[macro_export]
8975
macro_rules! throw_exhaust {
9076
($($tt:tt)*) => { return Err(err_exhaust!($($tt)*).into()) };

src/librustc_mir/const_eval/error.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,39 @@ use std::error::Error;
22
use std::fmt;
33

44
use super::InterpCx;
5-
use crate::interpret::{ConstEvalErr, InterpErrorInfo, Machine};
5+
use crate::interpret::{ConstEvalErr, InterpError, InterpErrorInfo, Machine, PanicInfo};
6+
7+
/// The CTFE machine has some custom error kinds.
68
#[derive(Clone, Debug)]
7-
pub enum ConstEvalError {
9+
pub enum ConstEvalErrKind {
810
NeedsRfc(String),
911
ConstAccessesStatic,
12+
Panic(PanicInfo<u64>),
1013
}
1114

12-
impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalError {
15+
// The errors become `MachineStop` with plain strings when being raised.
16+
// `ConstEvalErr` (in `librustc/mir/interpret/error.rs`) knows to
17+
// handle these.
18+
impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalErrKind {
1319
fn into(self) -> InterpErrorInfo<'tcx> {
14-
err_unsup!(Unsupported(self.to_string())).into()
20+
InterpError::MachineStop(Box::new(self.to_string())).into()
1521
}
1622
}
1723

18-
impl fmt::Display for ConstEvalError {
24+
impl fmt::Display for ConstEvalErrKind {
1925
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20-
use self::ConstEvalError::*;
26+
use self::ConstEvalErrKind::*;
2127
match *self {
2228
NeedsRfc(ref msg) => {
2329
write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg)
2430
}
2531
ConstAccessesStatic => write!(f, "constant accesses static"),
32+
Panic(ref msg) => write!(f, "{:?}", msg),
2633
}
2734
}
2835
}
2936

30-
impl Error for ConstEvalError {}
37+
impl Error for ConstEvalErrKind {}
3138

3239
/// Turn an interpreter error into something to report to the user.
3340
/// As a side-effect, if RUSTC_CTFE_BACKTRACE is set, this prints the backtrace.

src/librustc_mir/const_eval/machine.rs

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ use std::hash::Hash;
99
use rustc_data_structures::fx::FxHashMap;
1010

1111
use rustc_span::source_map::Span;
12+
use rustc_span::symbol::Symbol;
1213

1314
use crate::interpret::{
1415
self, snapshot, AllocId, Allocation, AssertMessage, GlobalId, ImmTy, InterpCx, InterpResult,
15-
Memory, MemoryKind, OpTy, PlaceTy, Pointer, Scalar,
16+
Memory, MemoryKind, OpTy, PanicInfo, PlaceTy, Pointer, Scalar,
1617
};
1718

1819
use super::error::*;
@@ -56,6 +57,32 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
5657
self.dump_place(*dest);
5758
return Ok(true);
5859
}
60+
61+
/// "Intercept" a function call to a panic-related function
62+
/// because we have something special to do for it.
63+
/// Returns `true` if an intercept happened.
64+
pub fn hook_panic_fn(
65+
&mut self,
66+
span: Span,
67+
instance: ty::Instance<'tcx>,
68+
args: &[OpTy<'tcx>],
69+
) -> InterpResult<'tcx, bool> {
70+
let def_id = instance.def_id();
71+
if Some(def_id) == self.tcx.lang_items().panic_fn()
72+
|| Some(def_id) == self.tcx.lang_items().begin_panic_fn()
73+
{
74+
// &'static str
75+
assert!(args.len() == 1);
76+
77+
let msg_place = self.deref_operand(args[0])?;
78+
let msg = Symbol::intern(self.read_str(msg_place)?);
79+
let span = self.find_closest_untracked_caller_location().unwrap_or(span);
80+
let (file, line, col) = self.location_triple_for_span(span);
81+
Err(ConstEvalErrKind::Panic(PanicInfo::Panic { msg, file, line, col }).into())
82+
} else {
83+
Ok(false)
84+
}
85+
}
5986
}
6087

6188
/// Number of steps until the detector even starts doing anything.
@@ -212,7 +239,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
212239
Ok(body) => *body,
213240
Err(err) => {
214241
if let err_unsup!(NoMirFor(ref path)) = err.kind {
215-
return Err(ConstEvalError::NeedsRfc(format!(
242+
return Err(ConstEvalErrKind::NeedsRfc(format!(
216243
"calling extern function `{}`",
217244
path
218245
))
@@ -246,7 +273,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
246273
}
247274
// An intrinsic that we do not support
248275
let intrinsic_name = ecx.tcx.item_name(instance.def_id());
249-
Err(ConstEvalError::NeedsRfc(format!("calling intrinsic `{}`", intrinsic_name)).into())
276+
Err(ConstEvalErrKind::NeedsRfc(format!("calling intrinsic `{}`", intrinsic_name)).into())
250277
}
251278

252279
fn assert_panic(
@@ -256,7 +283,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
256283
_unwind: Option<mir::BasicBlock>,
257284
) -> InterpResult<'tcx> {
258285
use rustc::mir::interpret::PanicInfo::*;
259-
Err(match msg {
286+
// Convert `PanicInfo<Operand>` to `PanicInfo<u64>`.
287+
let err = match msg {
260288
BoundsCheck { ref len, ref index } => {
261289
let len = ecx
262290
.read_immediate(ecx.eval_operand(len, None)?)
@@ -268,21 +296,21 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
268296
.expect("can't eval index")
269297
.to_scalar()?
270298
.to_machine_usize(&*ecx)?;
271-
err_panic!(BoundsCheck { len, index })
299+
BoundsCheck { len, index }
272300
}
273-
Overflow(op) => err_panic!(Overflow(*op)),
274-
OverflowNeg => err_panic!(OverflowNeg),
275-
DivisionByZero => err_panic!(DivisionByZero),
276-
RemainderByZero => err_panic!(RemainderByZero),
277-
ResumedAfterReturn(generator_kind) => err_panic!(ResumedAfterReturn(*generator_kind)),
278-
ResumedAfterPanic(generator_kind) => err_panic!(ResumedAfterPanic(*generator_kind)),
301+
Overflow(op) => Overflow(*op),
302+
OverflowNeg => OverflowNeg,
303+
DivisionByZero => DivisionByZero,
304+
RemainderByZero => RemainderByZero,
305+
ResumedAfterReturn(generator_kind) => ResumedAfterReturn(*generator_kind),
306+
ResumedAfterPanic(generator_kind) => ResumedAfterPanic(*generator_kind),
279307
Panic { .. } => bug!("`Panic` variant cannot occur in MIR"),
280-
}
281-
.into())
308+
};
309+
Err(ConstEvalErrKind::Panic(err).into())
282310
}
283311

284312
fn ptr_to_int(_mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx, u64> {
285-
Err(ConstEvalError::NeedsRfc("pointer-to-integer cast".to_string()).into())
313+
Err(ConstEvalErrKind::NeedsRfc("pointer-to-integer cast".to_string()).into())
286314
}
287315

288316
fn binary_ptr_op(
@@ -291,7 +319,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
291319
_left: ImmTy<'tcx>,
292320
_right: ImmTy<'tcx>,
293321
) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> {
294-
Err(ConstEvalError::NeedsRfc("pointer arithmetic or comparison".to_string()).into())
322+
Err(ConstEvalErrKind::NeedsRfc("pointer arithmetic or comparison".to_string()).into())
295323
}
296324

297325
fn find_foreign_static(
@@ -321,7 +349,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
321349
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
322350
_dest: PlaceTy<'tcx>,
323351
) -> InterpResult<'tcx> {
324-
Err(ConstEvalError::NeedsRfc("heap allocations via `box` keyword".to_string()).into())
352+
Err(ConstEvalErrKind::NeedsRfc("heap allocations via `box` keyword".to_string()).into())
325353
}
326354

327355
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,
355383
if memory_extra.can_access_statics {
356384
Ok(())
357385
} else {
358-
Err(ConstEvalError::ConstAccessesStatic.into())
386+
Err(ConstEvalErrKind::ConstAccessesStatic.into())
359387
}
360388
}
361389
}

src/librustc_mir/interpret/intrinsics.rs

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -376,32 +376,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
376376
Ok(true)
377377
}
378378

379-
/// "Intercept" a function call to a panic-related function
380-
/// because we have something special to do for it.
381-
/// Returns `true` if an intercept happened.
382-
pub fn hook_panic_fn(
383-
&mut self,
384-
span: Span,
385-
instance: ty::Instance<'tcx>,
386-
args: &[OpTy<'tcx, M::PointerTag>],
387-
) -> InterpResult<'tcx, bool> {
388-
let def_id = instance.def_id();
389-
if Some(def_id) == self.tcx.lang_items().panic_fn()
390-
|| Some(def_id) == self.tcx.lang_items().begin_panic_fn()
391-
{
392-
// &'static str
393-
assert!(args.len() == 1);
394-
395-
let msg_place = self.deref_operand(args[0])?;
396-
let msg = Symbol::intern(self.read_str(msg_place)?);
397-
let span = self.find_closest_untracked_caller_location().unwrap_or(span);
398-
let (file, line, col) = self.location_triple_for_span(span);
399-
throw_panic!(Panic { msg, file, line, col })
400-
} else {
401-
return Ok(false);
402-
}
403-
}
404-
405379
pub fn exact_div(
406380
&mut self,
407381
a: ImmTy<'tcx, M::PointerTag>,

src/librustc_mir/interpret/intrinsics/caller_location.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
5454
location
5555
}
5656

57-
pub fn alloc_caller_location_for_span(&mut self, span: Span) -> MPlaceTy<'tcx, M::PointerTag> {
58-
let (file, line, column) = self.location_triple_for_span(span);
59-
self.alloc_caller_location(file, line, column)
60-
}
61-
62-
pub(super) fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
57+
crate fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
6358
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
6459
let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
6560
(
@@ -68,4 +63,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
6863
caller.col_display as u32 + 1,
6964
)
7065
}
66+
67+
pub fn alloc_caller_location_for_span(&mut self, span: Span) -> MPlaceTy<'tcx, M::PointerTag> {
68+
let (file, line, column) = self.location_triple_for_span(span);
69+
self.alloc_caller_location(file, line, column)
70+
}
7171
}

0 commit comments

Comments
 (0)