diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index b03352d5fec6b..9ed31d9419ce7 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -973,6 +973,7 @@ impl Handler {
         self.inner.borrow_mut().span_bug(span, msg)
     }
 
+    /// For documentation on this, see `Session::delay_span_bug`.
     #[track_caller]
     pub fn delay_span_bug(
         &self,
@@ -1518,6 +1519,7 @@ impl HandlerInner {
         self.emit_diagnostic(diag.set_span(sp));
     }
 
+    /// For documentation on this, see `Session::delay_span_bug`.
     #[track_caller]
     fn delay_span_bug(
         &mut self,
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index 01fe72de61258..5ca4d260179ce 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -1,3 +1,13 @@
+/// A macro for triggering an ICE.
+/// Calling `bug` instead of panicking will result in a nicer error message and should
+/// therefore be prefered 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, [`Session::delay_span_bug`] may be useful.
+///
+/// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug
+/// [`span_bug`]: crate::span_bug
 #[macro_export]
 macro_rules! bug {
     () => ( $crate::bug!("impossible case reached") );
@@ -8,6 +18,14 @@ macro_rules! bug {
     });
 }
 
+/// 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, [`Session::delay_span_bug`] may be useful.
+///
+/// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug
 #[macro_export]
 macro_rules! span_bug {
     ($span:expr, $msg:expr) => ({ $crate::util::bug::span_bug_fmt($span, ::std::format_args!($msg)) });
diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs
index fd7045d6a03f2..b73ae59390535 100644
--- a/compiler/rustc_middle/src/util/bug.rs
+++ b/compiler/rustc_middle/src/util/bug.rs
@@ -35,8 +35,7 @@ fn opt_span_bug_fmt<S: Into<MultiSpan>>(
             (Some(tcx), None) => tcx.sess.diagnostic().bug(&msg),
             (None, _) => panic_any(msg),
         }
-    });
-    unreachable!();
+    })
 }
 
 /// A query to trigger a `delay_span_bug`. Clearly, if one has a `tcx` one can already trigger a
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 4a3d29414d6e5..1b2e8d9dc707b 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -590,7 +590,19 @@ impl Session {
     pub fn warn(&self, msg: impl Into<DiagnosticMessage>) {
         self.diagnostic().warn(msg)
     }
-    /// Delay a span_bug() call until abort_if_errors()
+
+    /// Ensures that compilation cannot succeed.
+    ///
+    /// If this function has been called but no errors have been emitted and
+    /// compilation succeeds, it will cause an internal compiler error (ICE).
+    ///
+    /// This can be used in code paths that should never run on successful compilations.
+    /// For example, it can be used to create an [`ErrorGuaranteed`]
+    /// (but you should prefer threading through the [`ErrorGuaranteed`] from an error emission directly).
+    ///
+    /// If no span is available, use [`DUMMY_SP`].
+    ///
+    /// [`DUMMY_SP`]: rustc_span::DUMMY_SP
     #[track_caller]
     pub fn delay_span_bug<S: Into<MultiSpan>>(
         &self,