diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 44af1b7653995..f9d8d858f16cc 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -127,6 +127,14 @@ fn mir_borrowck(
         Ok(tcx.arena.alloc(opaque_types))
     } else {
         let mut root_cx = BorrowCheckRootCtxt::new(tcx, def);
+        // We need to manually borrowck all nested bodies from the HIR as
+        // we do not generate MIR for dead code. Not doing so causes us to
+        // never check closures in dead code.
+        let nested_bodies = tcx.nested_bodies_within(def);
+        for def_id in nested_bodies {
+            root_cx.get_or_insert_nested(def_id);
+        }
+
         let PropagatedBorrowCheckResults { closure_requirements, used_mut_upvars } =
             do_mir_borrowck(&mut root_cx, def, None).0;
         debug_assert!(closure_requirements.is_none());
diff --git a/compiler/rustc_borrowck/src/root_cx.rs b/compiler/rustc_borrowck/src/root_cx.rs
index 13daa5c722148..66b526fa02a50 100644
--- a/compiler/rustc_borrowck/src/root_cx.rs
+++ b/compiler/rustc_borrowck/src/root_cx.rs
@@ -62,7 +62,10 @@ impl<'tcx> BorrowCheckRootCtxt<'tcx> {
         self.tainted_by_errors = Some(guar);
     }
 
-    fn get_or_insert_nested(&mut self, def_id: LocalDefId) -> &PropagatedBorrowCheckResults<'tcx> {
+    pub(super) fn get_or_insert_nested(
+        &mut self,
+        def_id: LocalDefId,
+    ) -> &PropagatedBorrowCheckResults<'tcx> {
         debug_assert_eq!(
             self.tcx.typeck_root_def_id(def_id.to_def_id()),
             self.root_def_id.to_def_id()
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 88f4c4ae4d361..2702aea96b54c 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -387,7 +387,7 @@ rustc_queries! {
         }
     }
 
-    query stalled_generators_within(
+    query nested_bodies_within(
         key: LocalDefId
     ) -> &'tcx ty::List<LocalDefId> {
         desc {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 3ea285d3d8eb8..071cbe83e5dbc 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -684,15 +684,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         self.opaque_types_defined_by(defining_anchor)
     }
 
-    fn opaque_types_and_generators_defined_by(
+    fn opaque_types_and_coroutines_defined_by(
         self,
         defining_anchor: Self::LocalDefId,
     ) -> Self::LocalDefIds {
         if self.next_trait_solver_globally() {
+            let coroutines_defined_by = self
+                .nested_bodies_within(defining_anchor)
+                .iter()
+                .filter(|def_id| self.is_coroutine(def_id.to_def_id()));
             self.mk_local_def_ids_from_iter(
-                self.opaque_types_defined_by(defining_anchor)
-                    .iter()
-                    .chain(self.stalled_generators_within(defining_anchor)),
+                self.opaque_types_defined_by(defining_anchor).iter().chain(coroutines_defined_by),
             )
         } else {
             self.opaque_types_defined_by(defining_anchor)
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index ea0f6b8dfba72..f79b6d44bfdfd 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -29,10 +29,10 @@ mod implied_bounds;
 mod instance;
 mod layout;
 mod needs_drop;
+mod nested_bodies;
 mod opaque_types;
 mod representability;
 pub mod sig_types;
-mod stalled_generators;
 mod structural_match;
 mod ty;
 
@@ -51,5 +51,5 @@ pub fn provide(providers: &mut Providers) {
     ty::provide(providers);
     instance::provide(providers);
     structural_match::provide(providers);
-    stalled_generators::provide(providers);
+    nested_bodies::provide(providers);
 }
diff --git a/compiler/rustc_ty_utils/src/nested_bodies.rs b/compiler/rustc_ty_utils/src/nested_bodies.rs
new file mode 100644
index 0000000000000..7c74d8eb63518
--- /dev/null
+++ b/compiler/rustc_ty_utils/src/nested_bodies.rs
@@ -0,0 +1,34 @@
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::intravisit::Visitor;
+use rustc_middle::query::Providers;
+use rustc_middle::ty::{self, TyCtxt};
+
+fn nested_bodies_within<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx ty::List<LocalDefId> {
+    let body = tcx.hir_body_owned_by(item);
+    let mut collector =
+        NestedBodiesVisitor { tcx, root_def_id: item.to_def_id(), nested_bodies: vec![] };
+    collector.visit_body(body);
+    tcx.mk_local_def_ids(&collector.nested_bodies)
+}
+
+struct NestedBodiesVisitor<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    root_def_id: DefId,
+    nested_bodies: Vec<LocalDefId>,
+}
+
+impl<'tcx> Visitor<'tcx> for NestedBodiesVisitor<'tcx> {
+    fn visit_nested_body(&mut self, id: hir::BodyId) {
+        let body_def_id = self.tcx.hir_body_owner_def_id(id);
+        if self.tcx.typeck_root_def_id(body_def_id.to_def_id()) == self.root_def_id {
+            self.nested_bodies.push(body_def_id);
+            let body = self.tcx.hir_body(id);
+            self.visit_body(body);
+        }
+    }
+}
+
+pub(super) fn provide(providers: &mut Providers) {
+    *providers = Providers { nested_bodies_within, ..*providers };
+}
diff --git a/compiler/rustc_ty_utils/src/stalled_generators.rs b/compiler/rustc_ty_utils/src/stalled_generators.rs
deleted file mode 100644
index 8b45e8b0f6f9a..0000000000000
--- a/compiler/rustc_ty_utils/src/stalled_generators.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit;
-use rustc_hir::intravisit::Visitor;
-use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, TyCtxt};
-
-fn stalled_generators_within<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    item: LocalDefId,
-) -> &'tcx ty::List<LocalDefId> {
-    if !tcx.next_trait_solver_globally() {
-        return ty::List::empty();
-    }
-
-    let body = tcx.hir_body_owned_by(item);
-    let mut collector =
-        StalledGeneratorVisitor { tcx, root_def_id: item.to_def_id(), stalled_coroutines: vec![] };
-    collector.visit_body(body);
-    tcx.mk_local_def_ids(&collector.stalled_coroutines)
-}
-
-struct StalledGeneratorVisitor<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    root_def_id: DefId,
-    stalled_coroutines: Vec<LocalDefId>,
-}
-
-impl<'tcx> Visitor<'tcx> for StalledGeneratorVisitor<'tcx> {
-    fn visit_nested_body(&mut self, id: hir::BodyId) {
-        if self.tcx.typeck_root_def_id(self.tcx.hir_body_owner_def_id(id).to_def_id())
-            == self.root_def_id
-        {
-            let body = self.tcx.hir_body(id);
-            self.visit_body(body);
-        }
-    }
-
-    fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
-        if let hir::ExprKind::Closure(&hir::Closure {
-            def_id,
-            kind: hir::ClosureKind::Coroutine(_),
-            ..
-        }) = ex.kind
-        {
-            self.stalled_coroutines.push(def_id);
-        }
-        intravisit::walk_expr(self, ex);
-    }
-}
-
-pub(super) fn provide(providers: &mut Providers) {
-    *providers = Providers { stalled_generators_within, ..*providers };
-}
diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs
index 8fa56c3599963..7d2654de44093 100644
--- a/compiler/rustc_type_ir/src/infer_ctxt.rs
+++ b/compiler/rustc_type_ir/src/infer_ctxt.rs
@@ -100,7 +100,7 @@ impl<I: Interner> TypingMode<I> {
     pub fn typeck_for_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
         TypingMode::Analysis {
             defining_opaque_types_and_generators: cx
-                .opaque_types_and_generators_defined_by(body_def_id),
+                .opaque_types_and_coroutines_defined_by(body_def_id),
         }
     }
 
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 6410da1f7409f..0fd2d9f3ad38b 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -341,7 +341,7 @@ pub trait Interner:
 
     fn opaque_types_defined_by(self, defining_anchor: Self::LocalDefId) -> Self::LocalDefIds;
 
-    fn opaque_types_and_generators_defined_by(
+    fn opaque_types_and_coroutines_defined_by(
         self,
         defining_anchor: Self::LocalDefId,
     ) -> Self::LocalDefIds;
diff --git a/tests/ui/nll/nested-bodies-in-dead-code.rs b/tests/ui/nll/nested-bodies-in-dead-code.rs
new file mode 100644
index 0000000000000..6ac68f5adbce8
--- /dev/null
+++ b/tests/ui/nll/nested-bodies-in-dead-code.rs
@@ -0,0 +1,28 @@
+//@ edition: 2024
+
+// Regression test for #140583. We want to borrowck nested
+// bodies even if they are in dead code. While not necessary for
+// soundness, it is desirable to error in such cases.
+
+fn main() {
+    return;
+    |x: &str| -> &'static str { x };
+    //~^ ERROR lifetime may not live long enough
+    || {
+        || {
+            let temp = 1;
+            let p: &'static u32 = &temp;
+            //~^ ERROR `temp` does not live long enough
+        };
+    };
+    const {
+        let temp = 1;
+        let p: &'static u32 = &temp;
+        //~^ ERROR `temp` does not live long enough
+    };
+    async {
+        let temp = 1;
+        let p: &'static u32 = &temp;
+        //~^ ERROR `temp` does not live long enough
+    };
+}
diff --git a/tests/ui/nll/nested-bodies-in-dead-code.stderr b/tests/ui/nll/nested-bodies-in-dead-code.stderr
new file mode 100644
index 0000000000000..da6ccff5777cd
--- /dev/null
+++ b/tests/ui/nll/nested-bodies-in-dead-code.stderr
@@ -0,0 +1,50 @@
+error: lifetime may not live long enough
+  --> $DIR/nested-bodies-in-dead-code.rs:9:33
+   |
+LL |     |x: &str| -> &'static str { x };
+   |         -                       ^ returning this value requires that `'1` must outlive `'static`
+   |         |
+   |         let's call the lifetime of this reference `'1`
+
+error[E0597]: `temp` does not live long enough
+  --> $DIR/nested-bodies-in-dead-code.rs:14:35
+   |
+LL |             let temp = 1;
+   |                 ---- binding `temp` declared here
+LL |             let p: &'static u32 = &temp;
+   |                    ------------   ^^^^^ borrowed value does not live long enough
+   |                    |
+   |                    type annotation requires that `temp` is borrowed for `'static`
+LL |
+LL |         };
+   |         - `temp` dropped here while still borrowed
+
+error[E0597]: `temp` does not live long enough
+  --> $DIR/nested-bodies-in-dead-code.rs:20:31
+   |
+LL |         let temp = 1;
+   |             ---- binding `temp` declared here
+LL |         let p: &'static u32 = &temp;
+   |                ------------   ^^^^^ borrowed value does not live long enough
+   |                |
+   |                type annotation requires that `temp` is borrowed for `'static`
+LL |
+LL |     };
+   |     - `temp` dropped here while still borrowed
+
+error[E0597]: `temp` does not live long enough
+  --> $DIR/nested-bodies-in-dead-code.rs:25:31
+   |
+LL |         let temp = 1;
+   |             ---- binding `temp` declared here
+LL |         let p: &'static u32 = &temp;
+   |                ------------   ^^^^^ borrowed value does not live long enough
+   |                |
+   |                type annotation requires that `temp` is borrowed for `'static`
+LL |
+LL |     };
+   |     - `temp` dropped here while still borrowed
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0597`.