Skip to main content

rustc_span/
fatal_error.rs

1/// Used as a return value to signify a fatal error occurred.
2#[derive(#[automatically_derived]
impl ::core::marker::Copy for FatalError { }Copy, #[automatically_derived]
impl ::core::clone::Clone for FatalError {
    #[inline]
    fn clone(&self) -> FatalError { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for FatalError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "FatalError")
    }
}Debug)]
3#[must_use]
4pub struct FatalError;
5
6use std::panic;
7
8pub use rustc_data_structures::FatalErrorMarker;
9
10// Don't implement Send on FatalError. This makes it impossible to `panic_any!(FatalError)`.
11// We don't want to invoke the panic handler and print a backtrace for fatal errors.
12impl !Send for FatalError {}
13
14impl FatalError {
15    pub fn raise(self) -> ! {
16        std::panic::resume_unwind(Box::new(FatalErrorMarker))
17    }
18}
19
20impl std::fmt::Display for FatalError {
21    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22        f.write_fmt(format_args!("fatal error"))write!(f, "fatal error")
23    }
24}
25
26impl std::error::Error for FatalError {}
27
28/// Runs a closure and catches unwinds triggered by fatal errors.
29///
30/// The compiler currently unwinds with a special sentinel value to abort
31/// compilation on fatal errors. This function catches that sentinel and turns
32/// the panic into a `Result` instead.
33pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, FatalError> {
34    panic::catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| {
35        if value.is::<FatalErrorMarker>() {
36            FatalError
37        } else {
38            panic::resume_unwind(value);
39        }
40    })
41}