| use std::fmt; | |
| use std::panic::{Location, panic_any}; | |
| use rustc_data_structures::AtomicRef; | |
| use crate::Span; | |
| /// Signifies that the compiler died with an explicit call to `.bug` or `.span_bug` rather than a | |
| /// failed assertion, etc. | |
| pub struct ExplicitBug; | |
| /// A macro for triggering an ICE. | |
| /// Calling `bug` instead of panicking will result in a nicer error message and should | |
| /// therefore be preferred over `panic`/`unreachable` or others. | |
| /// | |
| /// If you have a span available, you should use [`span_bug`] instead. | |
| /// | |
| /// If the bug should only be emitted when compilation didn't fail, | |
| /// [`DiagCtxtHandle::span_delayed_bug`] may be useful. | |
| /// | |
| /// [`DiagCtxtHandle::span_delayed_bug`]: ../../rustc_errors/struct.DiagCtxtHandle.html#method.span_delayed_bug | |
| /// [`span_bug`]: crate::span_bug | |
| pub macro bug { | |
| () => ( | |
| bug!("impossible case reached") | |
| ), | |
| ($($arg:tt)+) => ( | |
| // Use the full path of `bug_impl` to make sure rust-analyzer can resolve it, | |
| // to avoid bogus type errors about `()` versus `!`. | |
| $crate::macros::bug_impl(None, std::format_args!($($arg)+), Location::caller()) | |
| ), | |
| } | |
| /// A macro for triggering an ICE with a span. | |
| /// Calling `span_bug!` instead of panicking will result in a nicer error message and point | |
| /// at the code the compiler was compiling when it ICEd. This is the preferred way to trigger | |
| /// ICEs. | |
| /// | |
| /// If the bug should only be emitted when compilation didn't fail, | |
| /// [`DiagCtxtHandle::span_delayed_bug`] may be useful. | |
| /// | |
| /// [`DiagCtxtHandle::span_delayed_bug`]: ../../rustc_errors/struct.DiagCtxtHandle.html#method.span_delayed_bug | |
| pub macro span_bug($span:expr, $($arg:tt)+){ | |
| // Use the full path of `bug_impl` to make sure rust-analyzer can resolve it, | |
| // to avoid bogus type errors about `()` versus `!`. | |
| $crate::macros::bug_impl(Some($span), std::format_args!($($arg)+), Location::caller()) | |
| } | |
| #[cold] | |
| #[track_caller] | |
| pub fn bug_impl( | |
| span: Option<Span>, | |
| args: fmt::Arguments<'_>, | |
| location: &'static Location<'static>, | |
| ) -> ! { | |
| // Emit the bug without aborting. | |
| let emitted = (*EMIT_BUG_DIAGNOSTIC)(span, args, location); | |
| if emitted { | |
| // Panic with `ExplicitBug`, which tells `report_ice` that it's expected, e.g. originating | |
| // from `bug!` or `dcx.emit_bug(..)`. | |
| panic_any(ExplicitBug); | |
| } else { | |
| // Panic with just a string, which means it's unexpected. | |
| panic_any(format!("{args}")); | |
| } | |
| } | |
| pub static EMIT_BUG_DIAGNOSTIC: AtomicRef< | |
| fn(Option<Span>, fmt::Arguments<'_>, &'static Location<'static>) -> bool, | |
| > = AtomicRef::new(&(default_emit_bug_diagnostic as _)); | |
| fn default_emit_bug_diagnostic( | |
| _: Option<Span>, | |
| _args: fmt::Arguments<'_>, | |
| _location: &'static Location<'static>, | |
| ) -> bool { | |
| false | |
| } |