]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/const_eval/error.rs
2aafafd8205d1c9a8ab85fc1e82d871d79bf6eb0
[rust.git] / src / librustc_mir / const_eval / error.rs
1 use std::error::Error;
2 use std::fmt;
3
4 use rustc_middle::mir::AssertKind;
5 use rustc_span::Symbol;
6
7 use super::InterpCx;
8 use crate::interpret::{ConstEvalErr, InterpErrorInfo, Machine};
9
10 /// The CTFE machine has some custom error kinds.
11 #[derive(Clone, Debug)]
12 pub enum ConstEvalErrKind {
13     NeedsRfc(String),
14     ConstAccessesStatic,
15     ModifiedGlobal,
16     AssertFailure(AssertKind<u64>),
17     Panic { msg: Symbol, line: u32, col: u32, file: Symbol },
18 }
19
20 // The errors become `MachineStop` with plain strings when being raised.
21 // `ConstEvalErr` (in `librustc_middle/mir/interpret/error.rs`) knows to
22 // handle these.
23 impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalErrKind {
24     fn into(self) -> InterpErrorInfo<'tcx> {
25         err_machine_stop!(self.to_string()).into()
26     }
27 }
28
29 impl fmt::Display for ConstEvalErrKind {
30     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31         use self::ConstEvalErrKind::*;
32         match *self {
33             NeedsRfc(ref msg) => {
34                 write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg)
35             }
36             ConstAccessesStatic => write!(f, "constant accesses static"),
37             ModifiedGlobal => {
38                 write!(f, "modifying a static's initial value from another static's initializer")
39             }
40             AssertFailure(ref msg) => write!(f, "{:?}", msg),
41             Panic { msg, line, col, file } => {
42                 write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col)
43             }
44         }
45     }
46 }
47
48 impl Error for ConstEvalErrKind {}
49
50 /// Turn an interpreter error into something to report to the user.
51 /// As a side-effect, if RUSTC_CTFE_BACKTRACE is set, this prints the backtrace.
52 /// Should be called only if the error is actually going to to be reported!
53 pub fn error_to_const_error<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>(
54     ecx: &InterpCx<'mir, 'tcx, M>,
55     error: InterpErrorInfo<'tcx>,
56 ) -> ConstEvalErr<'tcx> {
57     error.print_backtrace();
58     let stacktrace = ecx.generate_stacktrace();
59     ConstEvalErr { error: error.kind, stacktrace, span: ecx.cur_span() }
60 }