diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 7111daa2ea9ab..4c81983c24296 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -336,7 +336,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         hir::InlineAsmOperand::Const { .. }
                         | hir::InlineAsmOperand::SymFn { .. }
                         | hir::InlineAsmOperand::SymStatic { .. } => {
-                            unreachable!()
+                            unreachable!("{op:?} is not a register operand");
                         }
                     };
 
@@ -380,7 +380,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                     {
                                         reg_sym.as_str()
                                     } else {
-                                        unreachable!();
+                                        unreachable!("{op:?} is not a register operand");
                                     }
                                 };
 
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 7c05724f64c95..83452c2228029 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -421,8 +421,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
             ItemKind::MacroDef(MacroDef { body, macro_rules }) => {
                 let body = P(self.lower_delim_args(body));
-                let DefKind::Macro(macro_kind) = self.tcx.def_kind(self.local_def_id(id)) else {
-                    unreachable!()
+                let def_id = self.local_def_id(id);
+                let def_kind = self.tcx.def_kind(def_id);
+                let DefKind::Macro(macro_kind) = def_kind else {
+                    unreachable!(
+                        "expected DefKind::Macro for macro item, found {}",
+                        def_kind.descr(def_id.to_def_id())
+                    );
                 };
                 let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules });
                 hir::ItemKind::Macro(macro_def, macro_kind)
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 01508375b1ace..5c252c3f9f2ce 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2815,7 +2815,7 @@ impl TraitRef<'_> {
         match self.path.res {
             Res::Def(DefKind::Trait | DefKind::TraitAlias, did) => Some(did),
             Res::Err => None,
-            _ => unreachable!(),
+            res => panic!("{res:?} did not resolve to a trait or trait alias"),
         }
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index caae6fa4f065e..2ae9f87f296ba 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -477,7 +477,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             ty::Const::new_misc_error(tcx, ty).into()
                         }
                     }
-                    _ => unreachable!(),
+                    (kind, arg) => span_bug!(
+                        self.span,
+                        "mismatched path argument for kind {kind:?}: found arg {arg:?}"
+                    ),
                 }
             }
 
@@ -1946,7 +1949,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     "s",
                 ),
                 [only] => (only.to_string(), ""),
-                [] => unreachable!(),
+                [] => unreachable!("expected at least one generic to prohibit"),
             };
             let last_span = *arg_spans.last().unwrap();
             let span: MultiSpan = arg_spans.into();
@@ -2555,8 +2558,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             if let Some(i) = (param.index as usize).checked_sub(generics.count() - lifetimes.len())
             {
                 // Resolve our own lifetime parameters.
-                let GenericParamDefKind::Lifetime { .. } = param.kind else { bug!() };
-                let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] else { bug!() };
+                let GenericParamDefKind::Lifetime { .. } = param.kind else {
+                    span_bug!(
+                        tcx.def_span(param.def_id),
+                        "only expected lifetime for opaque's own generics, got {:?}",
+                        param.kind
+                    );
+                };
+                let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] else {
+                    bug!(
+                        "expected lifetime argument for param {param:?}, found {:?}",
+                        &lifetimes[i]
+                    )
+                };
                 self.ast_region_to_region(lifetime, None).into()
             } else {
                 tcx.mk_param_from_def(param)
diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
index ce5426b51427f..dd5deb6f24455 100644
--- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
@@ -73,7 +73,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 | ty::ClauseKind::ConstArgHasType(..)
                 | ty::ClauseKind::WellFormed(_)
                 | ty::ClauseKind::ConstEvaluatable(_) => {
-                    bug!()
+                    span_bug!(span, "did not expect {pred} clause in object bounds");
                 }
             }
         }
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 00302ec831cef..4705d9350b0a3 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1086,8 +1086,14 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
             _ => return Ok(region),
         }
 
-        let e = if let Some(region) = self.map.get(&region) {
-            if let ty::ReEarlyParam(e) = region.kind() { e } else { bug!() }
+        let e = if let Some(id_region) = self.map.get(&region) {
+            if let ty::ReEarlyParam(e) = id_region.kind() {
+                e
+            } else {
+                bug!(
+                    "expected to map region {region} to early-bound identity region, but got {id_region}"
+                );
+            }
         } else {
             let guar = match region.kind() {
                 ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. })
@@ -1710,92 +1716,87 @@ fn compare_synthetic_generics<'tcx>(
                 trait_m.name
             );
             err.span_label(trait_span, "declaration in trait here");
-            match (impl_synthetic, trait_synthetic) {
+            if impl_synthetic {
                 // The case where the impl method uses `impl Trait` but the trait method uses
                 // explicit generics
-                (true, false) => {
-                    err.span_label(impl_span, "expected generic parameter, found `impl Trait`");
-                    let _: Option<_> = try {
-                        // try taking the name from the trait impl
-                        // FIXME: this is obviously suboptimal since the name can already be used
-                        // as another generic argument
-                        let new_name = tcx.opt_item_name(trait_def_id)?;
-                        let trait_m = trait_m.def_id.as_local()?;
-                        let trait_m = tcx.hir().expect_trait_item(trait_m);
-
-                        let impl_m = impl_m.def_id.as_local()?;
-                        let impl_m = tcx.hir().expect_impl_item(impl_m);
-
-                        // in case there are no generics, take the spot between the function name
-                        // and the opening paren of the argument list
-                        let new_generics_span = tcx.def_ident_span(impl_def_id)?.shrink_to_hi();
-                        // in case there are generics, just replace them
-                        let generics_span =
-                            impl_m.generics.span.substitute_dummy(new_generics_span);
-                        // replace with the generics from the trait
-                        let new_generics =
-                            tcx.sess.source_map().span_to_snippet(trait_m.generics.span).ok()?;
-
-                        err.multipart_suggestion(
-                            "try changing the `impl Trait` argument to a generic parameter",
-                            vec![
-                                // replace `impl Trait` with `T`
-                                (impl_span, new_name.to_string()),
-                                // replace impl method generics with trait method generics
-                                // This isn't quite right, as users might have changed the names
-                                // of the generics, but it works for the common case
-                                (generics_span, new_generics),
-                            ],
-                            Applicability::MaybeIncorrect,
-                        );
-                    };
-                }
+                err.span_label(impl_span, "expected generic parameter, found `impl Trait`");
+                let _: Option<_> = try {
+                    // try taking the name from the trait impl
+                    // FIXME: this is obviously suboptimal since the name can already be used
+                    // as another generic argument
+                    let new_name = tcx.opt_item_name(trait_def_id)?;
+                    let trait_m = trait_m.def_id.as_local()?;
+                    let trait_m = tcx.hir().expect_trait_item(trait_m);
+
+                    let impl_m = impl_m.def_id.as_local()?;
+                    let impl_m = tcx.hir().expect_impl_item(impl_m);
+
+                    // in case there are no generics, take the spot between the function name
+                    // and the opening paren of the argument list
+                    let new_generics_span = tcx.def_ident_span(impl_def_id)?.shrink_to_hi();
+                    // in case there are generics, just replace them
+                    let generics_span = impl_m.generics.span.substitute_dummy(new_generics_span);
+                    // replace with the generics from the trait
+                    let new_generics =
+                        tcx.sess.source_map().span_to_snippet(trait_m.generics.span).ok()?;
+
+                    err.multipart_suggestion(
+                        "try changing the `impl Trait` argument to a generic parameter",
+                        vec![
+                            // replace `impl Trait` with `T`
+                            (impl_span, new_name.to_string()),
+                            // replace impl method generics with trait method generics
+                            // This isn't quite right, as users might have changed the names
+                            // of the generics, but it works for the common case
+                            (generics_span, new_generics),
+                        ],
+                        Applicability::MaybeIncorrect,
+                    );
+                };
+            } else {
                 // The case where the trait method uses `impl Trait`, but the impl method uses
                 // explicit generics.
-                (false, true) => {
-                    err.span_label(impl_span, "expected `impl Trait`, found generic parameter");
-                    let _: Option<_> = try {
-                        let impl_m = impl_m.def_id.as_local()?;
-                        let impl_m = tcx.hir().expect_impl_item(impl_m);
-                        let (sig, _) = impl_m.expect_fn();
-                        let input_tys = sig.decl.inputs;
-
-                        struct Visitor(Option<Span>, hir::def_id::LocalDefId);
-                        impl<'v> intravisit::Visitor<'v> for Visitor {
-                            fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
-                                intravisit::walk_ty(self, ty);
-                                if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ty.kind
-                                    && let Res::Def(DefKind::TyParam, def_id) = path.res
-                                    && def_id == self.1.to_def_id()
-                                {
-                                    self.0 = Some(ty.span);
-                                }
+                err.span_label(impl_span, "expected `impl Trait`, found generic parameter");
+                let _: Option<_> = try {
+                    let impl_m = impl_m.def_id.as_local()?;
+                    let impl_m = tcx.hir().expect_impl_item(impl_m);
+                    let (sig, _) = impl_m.expect_fn();
+                    let input_tys = sig.decl.inputs;
+
+                    struct Visitor(Option<Span>, hir::def_id::LocalDefId);
+                    impl<'v> intravisit::Visitor<'v> for Visitor {
+                        fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
+                            intravisit::walk_ty(self, ty);
+                            if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ty.kind
+                                && let Res::Def(DefKind::TyParam, def_id) = path.res
+                                && def_id == self.1.to_def_id()
+                            {
+                                self.0 = Some(ty.span);
                             }
                         }
+                    }
 
-                        let mut visitor = Visitor(None, impl_def_id);
-                        for ty in input_tys {
-                            intravisit::Visitor::visit_ty(&mut visitor, ty);
-                        }
-                        let span = visitor.0?;
-
-                        let bounds = impl_m.generics.bounds_for_param(impl_def_id).next()?.bounds;
-                        let bounds = bounds.first()?.span().to(bounds.last()?.span());
-                        let bounds = tcx.sess.source_map().span_to_snippet(bounds).ok()?;
-
-                        err.multipart_suggestion(
-                            "try removing the generic parameter and using `impl Trait` instead",
-                            vec![
-                                // delete generic parameters
-                                (impl_m.generics.span, String::new()),
-                                // replace param usage with `impl Trait`
-                                (span, format!("impl {bounds}")),
-                            ],
-                            Applicability::MaybeIncorrect,
-                        );
-                    };
-                }
-                _ => unreachable!(),
+                    let mut visitor = Visitor(None, impl_def_id);
+                    for ty in input_tys {
+                        intravisit::Visitor::visit_ty(&mut visitor, ty);
+                    }
+                    let span = visitor.0?;
+
+                    let bounds = impl_m.generics.bounds_for_param(impl_def_id).next()?.bounds;
+                    let bounds = bounds.first()?.span().to(bounds.last()?.span());
+                    let bounds = tcx.sess.source_map().span_to_snippet(bounds).ok()?;
+
+                    err.multipart_suggestion(
+                        "try removing the generic parameter and using `impl Trait` instead",
+                        vec![
+                            // delete generic parameters
+                            (impl_m.generics.span, String::new()),
+                            // replace param usage with `impl Trait`
+                            (span, format!("impl {bounds}")),
+                        ],
+                        Applicability::MaybeIncorrect,
+                    );
+                };
             }
             error_found = Some(err.emit_unless(delay));
         }
@@ -1859,7 +1860,9 @@ fn compare_generic_param_kinds<'tcx>(
             // this is exhaustive so that anyone adding new generic param kinds knows
             // to make sure this error is reported for them.
             (Const { .. }, Const { .. }) | (Type { .. }, Type { .. }) => false,
-            (Lifetime { .. }, _) | (_, Lifetime { .. }) => unreachable!(),
+            (Lifetime { .. }, _) | (_, Lifetime { .. }) => {
+                bug!("lifetime params are expected to be filtered by `ty_const_params_of`")
+            }
         } {
             let param_impl_span = tcx.def_span(param_impl.def_id);
             let param_trait_span = tcx.def_span(param_trait.def_id);
@@ -1883,7 +1886,10 @@ fn compare_generic_param_kinds<'tcx>(
                     )
                 }
                 Type { .. } => format!("{prefix} type parameter"),
-                Lifetime { .. } => unreachable!(),
+                Lifetime { .. } => span_bug!(
+                    tcx.def_span(param.def_id),
+                    "lifetime params are expected to be filtered by `ty_const_params_of`"
+                ),
             };
 
             let trait_header_span = tcx.def_ident_span(tcx.parent(trait_item.def_id)).unwrap();
@@ -2187,7 +2193,10 @@ pub(super) fn check_type_bounds<'tcx>(
                 ..
             }) => ty.span,
             hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Type(ty), .. }) => ty.span,
-            _ => bug!(),
+            item => span_bug!(
+                tcx.def_span(impl_ty_def_id),
+                "cannot call `check_type_bounds` on item: {item:?}",
+            ),
         }
     };
     let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl_ty_def_id)?;
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
index f866543dd0d63..67796855ece85 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
@@ -262,7 +262,10 @@ fn report_mismatched_rpitit_signature<'tcx>(
 
     if tcx.asyncness(impl_m_def_id).is_async() && tcx.asyncness(trait_m_def_id).is_async() {
         let ty::Alias(ty::Projection, future_ty) = return_ty.kind() else {
-            bug!();
+            span_bug!(
+                tcx.def_span(trait_m_def_id),
+                "expected return type of async fn in trait to be a AFIT projection"
+            );
         };
         let Some(future_output_ty) = tcx
             .explicit_item_bounds(future_ty.def_id)
@@ -272,7 +275,7 @@ fn report_mismatched_rpitit_signature<'tcx>(
                 _ => None,
             })
         else {
-            bug!()
+            span_bug!(tcx.def_span(trait_m_def_id), "expected `Future` projection bound in AFIT");
         };
         return_ty = future_output_ty;
     }
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 2428fe6ae790a..7c9624206e539 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -49,7 +49,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
             16 => InlineAsmType::I16,
             32 => InlineAsmType::I32,
             64 => InlineAsmType::I64,
-            _ => unreachable!(),
+            width => bug!("unsupported pointer width: {width}"),
         };
 
         match *ty.kind() {
@@ -101,7 +101,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
                             16 => InlineAsmType::VecI16(size),
                             32 => InlineAsmType::VecI32(size),
                             64 => InlineAsmType::VecI64(size),
-                            _ => unreachable!(),
+                            width => bug!("unsupported pointer width: {width}"),
                         })
                     }
                     ty::Float(FloatTy::F32) => Some(InlineAsmType::VecF32(size)),
@@ -109,7 +109,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
                     _ => None,
                 }
             }
-            ty::Infer(_) => unreachable!(),
+            ty::Infer(_) => bug!("unexpected infer ty in asm operand"),
             _ => None,
         }
     }
@@ -136,8 +136,15 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
             ty::Adt(adt, args) if Some(adt.did()) == self.tcx.lang_items().maybe_uninit() => {
                 let fields = &adt.non_enum_variant().fields;
                 let ty = fields[FieldIdx::from_u32(1)].ty(self.tcx, args);
-                let ty::Adt(ty, args) = ty.kind() else { unreachable!() };
-                assert!(ty.is_manually_drop());
+                // FIXME: Are we just trying to map to the `T` in `MaybeUninit<T>`?
+                // If so, just get it from the args.
+                let ty::Adt(ty, args) = ty.kind() else {
+                    unreachable!("expected first field of `MaybeUninit` to be an ADT")
+                };
+                assert!(
+                    ty.is_manually_drop(),
+                    "expected first field of `MaybeUnit` to be `ManuallyDrop`"
+                );
                 let fields = &ty.non_enum_variant().fields;
                 let ty = fields[FieldIdx::from_u32(0)].ty(self.tcx, args);
                 self.get_asm_ty(ty)
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 1686479bd0e5a..64026cdfff417 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -204,11 +204,14 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
                 res = Err(err.emit());
             }
             // We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
-            match (tcx.impl_polarity(def_id), impl_.polarity) {
-                (ty::ImplPolarity::Positive, _) => {
+            match tcx.impl_polarity(def_id) {
+                ty::ImplPolarity::Positive => {
                     res = res.and(check_impl(tcx, item, impl_.self_ty, &impl_.of_trait));
                 }
-                (ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => {
+                ty::ImplPolarity::Negative => {
+                    let ast::ImplPolarity::Negative(span) = impl_.polarity else {
+                        bug!("impl_polarity query disagrees with impl's polarity in AST");
+                    };
                     // FIXME(#27579): what amount of WF checking do we need for neg impls?
                     if let hir::Defaultness::Default { .. } = impl_.defaultness {
                         let mut spans = vec![span];
@@ -222,10 +225,9 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
                         .emit());
                     }
                 }
-                (ty::ImplPolarity::Reservation, _) => {
+                ty::ImplPolarity::Reservation => {
                     // FIXME: what amount of WF checking do we need for reservation impls?
                 }
-                _ => unreachable!(),
             }
             res
         }
@@ -992,15 +994,6 @@ fn check_associated_item(
     })
 }
 
-fn item_adt_kind(kind: &ItemKind<'_>) -> Option<AdtKind> {
-    match kind {
-        ItemKind::Struct(..) => Some(AdtKind::Struct),
-        ItemKind::Union(..) => Some(AdtKind::Union),
-        ItemKind::Enum(..) => Some(AdtKind::Enum),
-        _ => None,
-    }
-}
-
 /// In a type definition, we check that to ensure that the types of the fields are well-formed.
 fn check_type_defn<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -1068,9 +1061,14 @@ fn check_type_defn<'tcx>(
                         hir_ty.span,
                         wfcx.body_def_id,
                         traits::FieldSized {
-                            adt_kind: match item_adt_kind(&item.kind) {
-                                Some(i) => i,
-                                None => bug!(),
+                            adt_kind: match &item.kind {
+                                ItemKind::Struct(..) => AdtKind::Struct,
+                                ItemKind::Union(..) => AdtKind::Union,
+                                ItemKind::Enum(..) => AdtKind::Enum,
+                                kind => span_bug!(
+                                    item.span,
+                                    "should be wfchecking an ADT, got {kind:?}"
+                                ),
                             },
                             span: hir_ty.span,
                             last,
@@ -1302,7 +1300,9 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
         | GenericParamDefKind::Const { has_default, .. } => {
             has_default && def.index >= generics.parent_count as u32
         }
-        GenericParamDefKind::Lifetime => unreachable!(),
+        GenericParamDefKind::Lifetime => {
+            span_bug!(tcx.def_span(def.def_id), "lifetime params can have no default")
+        }
     };
 
     // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
@@ -1750,15 +1750,15 @@ fn check_variances_for_type_defn<'tcx>(
             }
         }
         ItemKind::TyAlias(..) => {
-            if tcx.type_alias_is_lazy(item.owner_id) {
-                if tcx.type_of(item.owner_id).skip_binder().references_error() {
-                    return;
-                }
-            } else {
-                bug!();
+            assert!(
+                tcx.type_alias_is_lazy(item.owner_id),
+                "should not be computing variance of non-weak type alias"
+            );
+            if tcx.type_of(item.owner_id).skip_binder().references_error() {
+                return;
             }
         }
-        _ => bug!(),
+        kind => span_bug!(item.span, "cannot compute the variances of {kind:?}"),
     }
 
     let ty_predicates = tcx.predicates_of(item.owner_id);
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index fdd6424a19e2d..d176665e4c078 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -836,7 +836,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
     use rustc_hir::*;
 
     let Node::Item(item) = tcx.hir_node_by_def_id(def_id) else {
-        bug!();
+        bug!("expected ADT to be an item");
     };
 
     let repr = tcx.repr_options_of_def(def_id.to_def_id());
@@ -887,7 +887,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
 
             (adt_kind, variants)
         }
-        _ => bug!(),
+        _ => bug!("{:?} is not an ADT", item.owner_id.def_id),
     };
     tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr)
 }
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 0053af2b7dfe0..39ca1bba06545 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -97,8 +97,10 @@ pub(super) fn explicit_item_bounds(
                 item.span,
             ));
         }
-        // These should have been fed!
-        Some(ty::ImplTraitInTraitData::Impl { .. }) => unreachable!(),
+        Some(ty::ImplTraitInTraitData::Impl { .. }) => span_bug!(
+            tcx.def_span(def_id),
+            "item bounds for RPITIT in impl to be fed on def-id creation"
+        ),
         None => {}
     }
 
@@ -128,7 +130,7 @@ pub(super) fn explicit_item_bounds(
             let (hir::OpaqueTyOrigin::FnReturn(fn_def_id)
             | hir::OpaqueTyOrigin::AsyncFn(fn_def_id)) = *origin
             else {
-                bug!()
+                span_bug!(*span, "RPITIT cannot be a TAIT, but got origin {origin:?}");
             };
             let args = GenericArgs::identity_for_item(tcx, def_id);
             let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index de85a5d8626fa..41520718aa8d1 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -296,7 +296,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
                         hir::GenericBound::Outlives(lt) => {
                             (icx.astconv().ast_region_to_region(lt, None), lt.ident.span)
                         }
-                        _ => bug!(),
+                        bound => {
+                            span_bug!(
+                                bound.span(),
+                                "lifetime param bounds must be outlives, but found {bound:?}"
+                            )
+                        }
                     };
                     let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2))
                         .to_predicate(tcx);
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index a972c51e3eea0..5769fc5fe6408 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -1300,7 +1300,11 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                             what,
                         })
                     }
-                    _ => unreachable!(),
+                    kind => span_bug!(
+                        use_span,
+                        "did not expect to resolve lifetime to {}",
+                        kind.descr(param_def_id)
+                    ),
                 };
                 def = ResolvedArg::Error(guar);
             } else if let Some(body_id) = outermost_body {
@@ -1441,7 +1445,11 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                             what,
                         })
                     }
-                    _ => unreachable!(),
+                    kind => span_bug!(
+                        use_span,
+                        "did not expect to resolve non-lifetime param to {}",
+                        kind.descr(param_def_id.to_def_id())
+                    ),
                 };
                 self.map.defs.insert(hir_id, ResolvedArg::Error(guar));
             } else {
@@ -2123,7 +2131,7 @@ pub fn deny_non_region_late_bound(
 
     for (var, arg) in bound_vars {
         let Node::GenericParam(param) = tcx.hir_node_by_def_id(*var) else {
-            bug!();
+            span_bug!(tcx.def_span(*var), "expected bound-var def-id to resolve to param");
         };
 
         let what = match param.kind {
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 4b2ace748df3b..174217d3b70d1 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -20,7 +20,13 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
     use rustc_middle::ty::Ty;
     let hir_id = tcx.local_def_id_to_hir_id(def_id);
 
-    let Node::AnonConst(_) = tcx.hir_node(hir_id) else { panic!() };
+    let node = tcx.hir_node(hir_id);
+    let Node::AnonConst(_) = node else {
+        span_bug!(
+            tcx.def_span(def_id),
+            "expected anon const in `anon_const_type_of`, got {node:?}"
+        );
+    };
 
     let parent_node_id = tcx.hir().parent_id(hir_id);
     let parent_node = tcx.hir_node(parent_node_id);
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 8701626058d43..82e687135eb29 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -2003,18 +2003,14 @@ impl<'a> State<'a> {
         });
         self.word("|");
 
-        if let hir::FnRetTy::DefaultReturn(..) = decl.output {
-            return;
-        }
-
-        self.space_if_not_bol();
-        self.word_space("->");
         match decl.output {
             hir::FnRetTy::Return(ty) => {
+                self.space_if_not_bol();
+                self.word_space("->");
                 self.print_type(ty);
                 self.maybe_print_comment(ty.span.lo());
             }
-            hir::FnRetTy::DefaultReturn(..) => unreachable!(),
+            hir::FnRetTy::DefaultReturn(..) => {}
         }
     }
 
@@ -2179,7 +2175,7 @@ impl<'a> State<'a> {
                             GenericBound::Outlives(lt) => {
                                 self.print_lifetime(lt);
                             }
-                            _ => panic!(),
+                            _ => panic!("unexpected bound on lifetime param: {bound:?}"),
                         }
 
                         if i != 0 {
@@ -2216,16 +2212,14 @@ impl<'a> State<'a> {
     }
 
     fn print_fn_output(&mut self, decl: &hir::FnDecl<'_>) {
-        if let hir::FnRetTy::DefaultReturn(..) = decl.output {
-            return;
-        }
-
-        self.space_if_not_bol();
-        self.ibox(INDENT_UNIT);
-        self.word_space("->");
         match decl.output {
-            hir::FnRetTy::DefaultReturn(..) => unreachable!(),
-            hir::FnRetTy::Return(ty) => self.print_type(ty),
+            hir::FnRetTy::Return(ty) => {
+                self.space_if_not_bol();
+                self.ibox(INDENT_UNIT);
+                self.word_space("->");
+                self.print_type(ty);
+            }
+            hir::FnRetTy::DefaultReturn(..) => return,
         }
         self.end();
 
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index d89af297560b4..0de0365364c6a 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -149,7 +149,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 pub enum CastError {
     ErrorGuaranteed(ErrorGuaranteed),
 
@@ -271,7 +271,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                         match e {
                             CastError::NeedViaPtr => "a raw pointer",
                             CastError::NeedViaThinPtr => "a thin pointer",
-                            _ => bug!(),
+                            e => unreachable!("control flow means we should never encounter a {e:?}"),
                         }
                     ));
                 }
@@ -288,13 +288,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     self.cast_ty,
                     fcx,
                 )
-                .help(format!(
-                    "cast through {} first",
-                    match e {
-                        CastError::NeedViaInt => "an integer",
-                        _ => bug!(),
-                    }
-                ))
+                .help("cast through an integer first")
                 .emit();
             }
             CastError::IllegalCast => {
@@ -534,7 +528,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                 let unknown_cast_to = match e {
                     CastError::UnknownCastPtrKind => true,
                     CastError::UnknownExprPtrKind => false,
-                    _ => bug!(),
+                    e => unreachable!("control flow means we should never encounter a {e:?}"),
                 };
                 let (span, sub) = if unknown_cast_to {
                     (self.cast_span, errors::CastUnknownPointerSub::To(self.cast_span))
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 22af79e02a70f..61236c07135cd 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1182,14 +1182,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     Adjust::Pointer(PointerCoercion::ClosureFnPointer(a_sig.unsafety()))
                 }
                 ty::FnDef(..) => Adjust::Pointer(PointerCoercion::ReifyFnPointer),
-                _ => unreachable!(),
+                _ => span_bug!(cause.span, "should not try to coerce a {prev_ty} to a fn pointer"),
             };
             let next_adjustment = match new_ty.kind() {
                 ty::Closure(..) => {
                     Adjust::Pointer(PointerCoercion::ClosureFnPointer(b_sig.unsafety()))
                 }
                 ty::FnDef(..) => Adjust::Pointer(PointerCoercion::ReifyFnPointer),
-                _ => unreachable!(),
+                _ => span_bug!(new.span, "should not try to coerce a {new_ty} to a fn pointer"),
             };
             for expr in exprs.iter().map(|e| e.as_coercion_site()) {
                 self.apply_adjustments(
@@ -1918,7 +1918,7 @@ where
 
 impl AsCoercionSite for ! {
     fn as_coercion_site(&self) -> &hir::Expr<'_> {
-        unreachable!()
+        *self
     }
 }
 
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 580586f626771..8b666c634257f 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -331,13 +331,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty_op: |ty| {
                 if let ty::Infer(infer) = ty.kind() {
                     match infer {
-                        ty::InferTy::TyVar(_) => self.next_ty_var(TypeVariableOrigin {
+                        ty::TyVar(_) => self.next_ty_var(TypeVariableOrigin {
                             kind: TypeVariableOriginKind::MiscVariable,
                             span: DUMMY_SP,
                         }),
-                        ty::InferTy::IntVar(_) => self.next_int_var(),
-                        ty::InferTy::FloatVar(_) => self.next_float_var(),
-                        _ => bug!(),
+                        ty::IntVar(_) => self.next_int_var(),
+                        ty::FloatVar(_) => self.next_float_var(),
+                        ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
+                            bug!("unexpected fresh ty outside of the trait solver")
+                        }
                     }
                 } else {
                     ty
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 725f327d835dc..80265cf31e672 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2087,7 +2087,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let names = names.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>();
                     format!("{} and `{last}` ", names.join(", "))
                 }
-                [] => unreachable!(),
+                [] => bug!("expected at least one private field to report"),
             };
             err.note(format!(
                 "{}private field{s} {names}that {were} not provided",
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 2ab7bb86354c6..3f97b24aa59bf 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -993,7 +993,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }) {
                         match e {
                             Error::Missing(expected_idx) => missing_idxs.push(expected_idx),
-                            _ => unreachable!(),
+                            _ => unreachable!(
+                                "control flow ensures that we should always get an `Error::Missing`"
+                            ),
                         }
                     }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 28f377083f68f..1650aaeb4957a 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -2072,8 +2072,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     Some(CtorKind::Fn) => ("(".to_owned(), ")"),
                     None => (format!(" {{ {field_name}: "), " }"),
 
-                    // unit variants don't have fields
-                    Some(CtorKind::Const) => unreachable!(),
+                    Some(CtorKind::Const) => unreachable!("unit variants don't have fields"),
                 };
 
                 // Suggest constructor as deep into the block tree as possible.
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index e7af7da205c61..b2ead3cd40b74 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -415,7 +415,9 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                             )
                             .into()
                     }
-                    _ => unreachable!(),
+                    (kind, arg) => {
+                        bug!("mismatched method arg kind {kind:?} in turbofish: {arg:?}")
+                    }
                 }
             }
 
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 165fc630787e7..be21fd5f0a630 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1820,7 +1820,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         fn joined_uncovered_patterns(witnesses: &[&Ident]) -> String {
             const LIMIT: usize = 3;
             match witnesses {
-                [] => bug!(),
+                [] => {
+                    unreachable!(
+                        "expected an uncovered pattern, otherwise why are we emitting an error?"
+                    )
+                }
                 [witness] => format!("`{witness}`"),
                 [head @ .., tail] if head.len() < LIMIT => {
                     let head: Vec<_> = head.iter().map(<_>::to_string).collect();
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index 6608fdab9d087..fe58fc7122c59 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -103,15 +103,19 @@ impl<'tcx> InferCtxt<'tcx> {
             }
 
             // We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm.
-            (
-                ty::Alias(..),
-                ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
-            )
-            | (
-                ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
-                ty::Alias(..),
-            ) if self.next_trait_solver() => {
-                bug!()
+            (ty::Alias(..), ty::Infer(ty::TyVar(_))) | (ty::Infer(ty::TyVar(_)), ty::Alias(..))
+                if self.next_trait_solver() =>
+            {
+                bug!(
+                    "We do not expect to encounter `TyVar` this late in combine \
+                    -- they should have been handled earlier"
+                )
+            }
+            (_, ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)))
+            | (ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), _)
+                if self.next_trait_solver() =>
+            {
+                bug!("We do not expect to encounter `Fresh` variables in the new solver")
             }
 
             (_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index 8fe6c1b0d86fd..1caa9aa8cd688 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -232,7 +232,9 @@ fn ty_to_string<'tcx>(
 /// something users are familiar with. Directly printing the `fn_sig` of closures also
 /// doesn't work as they actually use the "rust-call" API.
 fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
-    let ty::Closure(_, args) = ty.kind() else { unreachable!() };
+    let ty::Closure(_, args) = ty.kind() else {
+        bug!("cannot convert non-closure to fn str in `closure_as_fn_str`")
+    };
     let fn_sig = args.as_closure().sig();
     let args = fn_sig
         .inputs()
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index 362bb8169102c..1e365848e070d 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -375,7 +375,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     err.span_note(span, "the lifetime requirement is introduced here");
                     err
                 } else {
-                    unreachable!()
+                    unreachable!(
+                        "control flow ensures we have a `BindingObligation` or `ExprBindingObligation` here..."
+                    )
                 }
             }
             infer::Subtype(box trace) => {
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index d707c30206df9..ab3c976a351a0 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -247,7 +247,9 @@ where
         let (a, b) = match (a.kind(), b.kind()) {
             (&ty::Alias(ty::Opaque, ..), _) => (a, generalize(b, false)?),
             (_, &ty::Alias(ty::Opaque, ..)) => (generalize(a, true)?, b),
-            _ => unreachable!(),
+            _ => unreachable!(
+                "expected at least one opaque type in `relate_opaques`, got {a} and {b}."
+            ),
         };
         let cause = ObligationCause::dummy_with_span(self.delegate.span());
         let obligations = self
@@ -707,7 +709,9 @@ where
             ),
             // FIXME(deferred_projection_equality): Implement this when we trigger it.
             // Probably just need to do nothing here.
-            ty::Variance::Bivariant => unreachable!(),
+            ty::Variance::Bivariant => {
+                unreachable!("cannot defer an alias-relate goal with Bivariant variance (yet?)")
+            }
         })]);
     }
 }
diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs
index 45df22d44e810..47038cfd46878 100644
--- a/compiler/rustc_infer/src/infer/outlives/components.rs
+++ b/compiler/rustc_infer/src/infer/outlives/components.rs
@@ -203,7 +203,9 @@ pub(super) fn compute_alias_components_recursive<'tcx>(
     out: &mut SmallVec<[Component<'tcx>; 4]>,
     visited: &mut SsoHashSet<GenericArg<'tcx>>,
 ) {
-    let ty::Alias(kind, alias_ty) = alias_ty.kind() else { bug!() };
+    let ty::Alias(kind, alias_ty) = alias_ty.kind() else {
+        unreachable!("can only call `compute_alias_components_recursive` on an alias type")
+    };
     let opt_variances = if *kind == ty::Opaque { tcx.variances_of(alias_ty.def_id) } else { &[] };
     for (index, child) in alias_ty.args.iter().enumerate() {
         if opt_variances.get(index) == Some(&ty::Bivariant) {
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index 9d99344d5bdfb..310cf113b11b6 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -71,7 +71,7 @@ impl std::fmt::Debug for ConstInt {
                         (4, _) => write!(fmt, "_i32")?,
                         (8, _) => write!(fmt, "_i64")?,
                         (16, _) => write!(fmt, "_i128")?,
-                        _ => bug!(),
+                        (sz, _) => bug!("unexpected int size i{sz}"),
                     }
                 }
                 Ok(())
@@ -105,7 +105,7 @@ impl std::fmt::Debug for ConstInt {
                         (4, _) => write!(fmt, "_u32")?,
                         (8, _) => write!(fmt, "_u64")?,
                         (16, _) => write!(fmt, "_u128")?,
-                        _ => bug!(),
+                        (sz, _) => bug!("unexpected unsigned int size u{sz}"),
                     }
                 }
                 Ok(())
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 8b1d33848eab3..8b2b76764e646 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -421,13 +421,10 @@ impl<'tcx> TyCtxt<'tcx> {
 
         let impl_args = match *self.type_of(impl_def_id).instantiate_identity().kind() {
             ty::Adt(def_, args) if def_ == def => args,
-            _ => bug!(),
+            _ => span_bug!(self.def_span(impl_def_id), "expected ADT for self type of `Drop` impl"),
         };
 
-        let item_args = match *self.type_of(def.did()).instantiate_identity().kind() {
-            ty::Adt(def_, args) if def_ == def => args,
-            _ => bug!(),
-        };
+        let item_args = ty::GenericArgs::identity_for_item(self, def.did());
 
         let result = iter::zip(item_args, impl_args)
             .filter(|&(_, k)| {
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index c63c7987f5efb..dae83d4b41b23 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -640,7 +640,9 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -
         }
         DefKind::Closure if coroutine_kind.is_some() => {
             let coroutine_ty = tcx.type_of(def_id).instantiate_identity();
-            let ty::Coroutine(_, args, _) = coroutine_ty.kind() else { bug!() };
+            let ty::Coroutine(_, args, _) = coroutine_ty.kind() else {
+                bug!("expected type of coroutine-like closure to be a coroutine")
+            };
             let args = args.as_coroutine();
             let yield_ty = args.yield_ty();
             let return_ty = args.return_ty();
@@ -648,7 +650,9 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -
         }
         DefKind::Closure => {
             let closure_ty = tcx.type_of(def_id).instantiate_identity();
-            let ty::Closure(_, args) = closure_ty.kind() else { bug!() };
+            let ty::Closure(_, args) = closure_ty.kind() else {
+                bug!("expected type of closure to be a closure")
+            };
             let args = args.as_closure();
             let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), args.sig());
             let self_ty = match args.kind() {
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 31874b29bb3b8..ab88463826a2b 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -782,7 +782,7 @@ impl<'tcx> Cx<'tcx> {
             hir::ExprKind::Tup(fields) => ExprKind::Tuple { fields: self.mirror_exprs(fields) },
 
             hir::ExprKind::Yield(v, _) => ExprKind::Yield { value: self.mirror_expr(v) },
-            hir::ExprKind::Err(_) => unreachable!(),
+            hir::ExprKind::Err(_) => unreachable!("cannot lower a `hir::ExprKind::Err` to THIR"),
         };
 
         Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 391d65b338d55..a7f2377219304 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -492,8 +492,9 @@ impl<'tcx> ConstToPat<'tcx> {
                 PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
             }
             ty::FnPtr(..) => {
-                // Valtree construction would never succeed for these, so this is unreachable.
-                unreachable!()
+                unreachable!(
+                    "Valtree construction would never succeed for FnPtr, so this is unreachable."
+                )
             }
             _ => {
                 let err = InvalidPattern { span, non_sm_ty: ty };
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
index 2fe51b400ec21..980ef86236656 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
@@ -203,7 +203,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                     )
                     .into(),
                     ty::AssocKind::Type => Ty::new_error(tcx, guar).into(),
-                    ty::AssocKind::Fn => unreachable!(),
+                    // This makes no sense...
+                    ty::AssocKind::Fn => span_bug!(
+                        tcx.def_span(assoc_def.item.def_id),
+                        "cannot project to an associated function"
+                    ),
                 };
                 ecx.eq(goal.param_env, goal.predicate.term, error_term)
                     .expect("expected goal term to be fully unconstrained");
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 9536fde7c93d1..deb50e6aefdb3 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -256,7 +256,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
                     Err(NoSolution)
                 }
             }
-            ty::ImplPolarity::Reservation => bug!(),
+            // FIXME: Goal polarity should be split from impl polarity
+            ty::ImplPolarity::Reservation => {
+                bug!("we never expect a `Reservation` polarity in a trait goal")
+            }
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 88ebea700210b..818d14366596c 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -487,7 +487,7 @@ fn plug_infer_with_placeholders<'tcx>(
                         ),
                     )
                 else {
-                    bug!()
+                    bug!("we always expect to be able to plug an infer var with placeholder")
                 };
                 assert_eq!(obligations, &[]);
                 ControlFlow::Continue(())
@@ -510,7 +510,7 @@ fn plug_infer_with_placeholders<'tcx>(
                         ),
                     )
                 else {
-                    bug!()
+                    bug!("we always expect to be able to plug an infer var with placeholder")
                 };
                 assert_eq!(obligations, &[]);
                 ControlFlow::Continue(())
@@ -544,7 +544,7 @@ fn plug_infer_with_placeholders<'tcx>(
                             ),
                         )
                     else {
-                        bug!()
+                        bug!("we always expect to be able to plug an infer var with placeholder")
                     };
                     assert_eq!(obligations, &[]);
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index b3bb0a9fcb770..5cc934e7bc52a 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -250,7 +250,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         err.emit();
 
         self.tcx.sess.abort_if_errors();
-        bug!();
+        // FIXME: this should be something like `build_overflow_error_fatal`, which returns
+        // `DiagnosticBuilder<', !>`. Then we don't even need anything after that `emit()`.
+        unreachable!(
+            "did not expect compilation to continue after `abort_if_errors`, \
+            since an error was definitely emitted!"
+        );
     }
 
     fn build_overflow_error<T>(
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 4c3eb05819f33..d5635812c7405 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -191,7 +191,9 @@ impl<'tcx> ProjectionCandidateSet<'tcx> {
                 match (current, candidate) {
                     (ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (),
                     (ParamEnv(..), _) => return false,
-                    (_, ParamEnv(..)) => unreachable!(),
+                    (_, ParamEnv(..)) => bug!(
+                        "should never prefer non-param-env candidates over param-env candidates"
+                    ),
                     (_, _) => convert_to_ambiguous = (),
                 }
             }
@@ -2080,10 +2082,11 @@ fn confirm_coroutine_candidate<'cx, 'tcx>(
     obligation: &ProjectionTyObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
-    let ty::Coroutine(_, args, _) =
-        selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
-    else {
-        unreachable!()
+    let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
+    let ty::Coroutine(_, args, _) = self_ty.kind() else {
+        unreachable!(
+            "expected coroutine self type for built-in coroutine candidate, found {self_ty}"
+        )
     };
     let coroutine_sig = args.as_coroutine().sig();
     let Normalized { value: coroutine_sig, obligations } = normalize_with_depth(
@@ -2113,7 +2116,10 @@ fn confirm_coroutine_candidate<'cx, 'tcx>(
     } else if name == sym::Yield {
         yield_ty
     } else {
-        bug!()
+        span_bug!(
+            tcx.def_span(obligation.predicate.def_id),
+            "unexpected associated type: `Coroutine::{name}`"
+        );
     };
 
     let predicate = ty::ProjectionPredicate {
@@ -2131,10 +2137,11 @@ fn confirm_future_candidate<'cx, 'tcx>(
     obligation: &ProjectionTyObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
-    let ty::Coroutine(_, args, _) =
-        selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
-    else {
-        unreachable!()
+    let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
+    let ty::Coroutine(_, args, _) = self_ty.kind() else {
+        unreachable!(
+            "expected coroutine self type for built-in async future candidate, found {self_ty}"
+        )
     };
     let coroutine_sig = args.as_coroutine().sig();
     let Normalized { value: coroutine_sig, obligations } = normalize_with_depth(
@@ -2174,10 +2181,9 @@ fn confirm_iterator_candidate<'cx, 'tcx>(
     obligation: &ProjectionTyObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
-    let ty::Coroutine(_, args, _) =
-        selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
-    else {
-        unreachable!()
+    let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
+    let ty::Coroutine(_, args, _) = self_ty.kind() else {
+        unreachable!("expected coroutine self type for built-in gen candidate, found {self_ty}")
     };
     let gen_sig = args.as_coroutine().sig();
     let Normalized { value: gen_sig, obligations } = normalize_with_depth(
@@ -2341,9 +2347,9 @@ fn confirm_closure_candidate<'cx, 'tcx>(
     obligation: &ProjectionTyObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
-    let ty::Closure(_, args) = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
-    else {
-        unreachable!()
+    let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
+    let ty::Closure(_, args) = self_ty.kind() else {
+        unreachable!("expected closure self type for closure candidate, found {self_ty}")
     };
     let closure_sig = args.as_closure().sig();
     let Normalized { value: closure_sig, obligations } = normalize_with_depth(
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 4728fcf3301c0..ed55533bc551a 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -285,7 +285,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
                     ty::Projection => tcx.normalize_projection_ty(c_data),
                     ty::Weak => tcx.normalize_weak_ty(c_data),
                     ty::Inherent => tcx.normalize_inherent_projection_ty(c_data),
-                    _ => unreachable!(),
+                    kind => unreachable!("did not expect {kind:?} due to match arm above"),
                 }?;
                 // We don't expect ambiguity.
                 if !result.value.is_proven() {
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index 10528696b2d70..ba6ed29877409 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -184,7 +184,9 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
                 push_outlives_components(tcx, ty_a, &mut components);
                 implied_bounds.extend(implied_bounds_from_components(r_b, components))
             }
-            ty::GenericArgKind::Const(_) => unreachable!(),
+            ty::GenericArgKind::Const(_) => {
+                unreachable!("consts do not participate in outlives bounds")
+            }
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 4a342a7f6b146..7e3d304d1cdf0 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -942,8 +942,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let a_ty = self.infcx.shallow_resolve(predicate.self_ty());
         let b_ty = self.infcx.shallow_resolve(predicate.trait_ref.args.type_at(1));
 
-        let ty::Dynamic(a_data, a_region, ty::Dyn) = *a_ty.kind() else { bug!() };
-        let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else { bug!() };
+        let ty::Dynamic(a_data, a_region, ty::Dyn) = *a_ty.kind() else {
+            bug!("expected `dyn` type in `confirm_trait_upcasting_unsize_candidate`")
+        };
+        let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else {
+            bug!("expected `dyn` type in `confirm_trait_upcasting_unsize_candidate`")
+        };
 
         let source_principal = a_data.principal().unwrap().with_self_ty(tcx, a_ty);
         let unnormalized_upcast_principal =