File tree Expand file tree Collapse file tree 11 files changed +140
-64
lines changed Expand file tree Collapse file tree 11 files changed +140
-64
lines changed Original file line number Diff line number Diff line change @@ -127,6 +127,14 @@ fn mir_borrowck(
127127 Ok ( tcx. arena . alloc ( opaque_types) )
128128 } else {
129129 let mut root_cx = BorrowCheckRootCtxt :: new ( tcx, def) ;
130+ // We need to manually borrowck all nested bodies from the HIR as
131+ // we do not generate MIR for dead code. Not doing so causes us to
132+ // never check closures in dead code.
133+ let nested_bodies = tcx. nested_bodies_within ( def) ;
134+ for def_id in nested_bodies {
135+ root_cx. get_or_insert_nested ( def_id) ;
136+ }
137+
130138 let PropagatedBorrowCheckResults { closure_requirements, used_mut_upvars } =
131139 do_mir_borrowck ( & mut root_cx, def, None ) . 0 ;
132140 debug_assert ! ( closure_requirements. is_none( ) ) ;
Original file line number Diff line number Diff line change @@ -62,7 +62,10 @@ impl<'tcx> BorrowCheckRootCtxt<'tcx> {
6262 self . tainted_by_errors = Some ( guar) ;
6363 }
6464
65- fn get_or_insert_nested ( & mut self , def_id : LocalDefId ) -> & PropagatedBorrowCheckResults < ' tcx > {
65+ pub ( super ) fn get_or_insert_nested (
66+ & mut self ,
67+ def_id : LocalDefId ,
68+ ) -> & PropagatedBorrowCheckResults < ' tcx > {
6669 debug_assert_eq ! (
6770 self . tcx. typeck_root_def_id( def_id. to_def_id( ) ) ,
6871 self . root_def_id. to_def_id( )
Original file line number Diff line number Diff line change @@ -387,7 +387,7 @@ rustc_queries! {
387387 }
388388 }
389389
390- query stalled_generators_within (
390+ query nested_bodies_within (
391391 key: LocalDefId
392392 ) -> & ' tcx ty:: List <LocalDefId > {
393393 desc {
Original file line number Diff line number Diff line change @@ -684,15 +684,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
684684 self . opaque_types_defined_by ( defining_anchor)
685685 }
686686
687- fn opaque_types_and_generators_defined_by (
687+ fn opaque_types_and_coroutines_defined_by (
688688 self ,
689689 defining_anchor : Self :: LocalDefId ,
690690 ) -> Self :: LocalDefIds {
691691 if self . next_trait_solver_globally ( ) {
692+ let coroutines_defined_by = self
693+ . nested_bodies_within ( defining_anchor)
694+ . iter ( )
695+ . filter ( |def_id| self . is_coroutine ( def_id. to_def_id ( ) ) ) ;
692696 self . mk_local_def_ids_from_iter (
693- self . opaque_types_defined_by ( defining_anchor)
694- . iter ( )
695- . chain ( self . stalled_generators_within ( defining_anchor) ) ,
697+ self . opaque_types_defined_by ( defining_anchor) . iter ( ) . chain ( coroutines_defined_by) ,
696698 )
697699 } else {
698700 self . opaque_types_defined_by ( defining_anchor)
Original file line number Diff line number Diff line change @@ -29,10 +29,10 @@ mod implied_bounds;
2929mod instance;
3030mod layout;
3131mod needs_drop;
32+ mod nested_bodies;
3233mod opaque_types;
3334mod representability;
3435pub mod sig_types;
35- mod stalled_generators;
3636mod structural_match;
3737mod ty;
3838
@@ -51,5 +51,5 @@ pub fn provide(providers: &mut Providers) {
5151 ty:: provide ( providers) ;
5252 instance:: provide ( providers) ;
5353 structural_match:: provide ( providers) ;
54- stalled_generators :: provide ( providers) ;
54+ nested_bodies :: provide ( providers) ;
5555}
Original file line number Diff line number Diff line change 1+ use rustc_hir as hir;
2+ use rustc_hir:: def_id:: { DefId , LocalDefId } ;
3+ use rustc_hir:: intravisit:: Visitor ;
4+ use rustc_middle:: query:: Providers ;
5+ use rustc_middle:: ty:: { self , TyCtxt } ;
6+
7+ fn nested_bodies_within < ' tcx > (
8+ tcx : TyCtxt < ' tcx > ,
9+ item : LocalDefId ,
10+ ) -> & ' tcx ty:: List < LocalDefId > {
11+ let body = tcx. hir_body_owned_by ( item) ;
12+ let mut collector =
13+ NestedBodiesVisitor { tcx, root_def_id : item. to_def_id ( ) , nested_bodies : vec ! [ ] } ;
14+ collector. visit_body ( body) ;
15+ tcx. mk_local_def_ids ( & collector. nested_bodies )
16+ }
17+
18+ struct NestedBodiesVisitor < ' tcx > {
19+ tcx : TyCtxt < ' tcx > ,
20+ root_def_id : DefId ,
21+ nested_bodies : Vec < LocalDefId > ,
22+ }
23+
24+ impl < ' tcx > Visitor < ' tcx > for NestedBodiesVisitor < ' tcx > {
25+ fn visit_nested_body ( & mut self , id : hir:: BodyId ) {
26+ let body_def_id = self . tcx . hir_body_owner_def_id ( id) ;
27+ if self . tcx . typeck_root_def_id ( body_def_id. to_def_id ( ) )
28+ == self . root_def_id
29+ {
30+ self . nested_bodies . push ( body_def_id) ;
31+ let body = self . tcx . hir_body ( id) ;
32+ self . visit_body ( body) ;
33+ }
34+ }
35+ }
36+
37+ pub ( super ) fn provide ( providers : & mut Providers ) {
38+ * providers = Providers { nested_bodies_within, ..* providers } ;
39+ }
Load Diff This file was deleted.
Original file line number Diff line number Diff line change @@ -100,7 +100,7 @@ impl<I: Interner> TypingMode<I> {
100100 pub fn typeck_for_body ( cx : I , body_def_id : I :: LocalDefId ) -> TypingMode < I > {
101101 TypingMode :: Analysis {
102102 defining_opaque_types_and_generators : cx
103- . opaque_types_and_generators_defined_by ( body_def_id) ,
103+ . opaque_types_and_coroutines_defined_by ( body_def_id) ,
104104 }
105105 }
106106
Original file line number Diff line number Diff line change @@ -341,7 +341,7 @@ pub trait Interner:
341341
342342 fn opaque_types_defined_by ( self , defining_anchor : Self :: LocalDefId ) -> Self :: LocalDefIds ;
343343
344- fn opaque_types_and_generators_defined_by (
344+ fn opaque_types_and_coroutines_defined_by (
345345 self ,
346346 defining_anchor : Self :: LocalDefId ,
347347 ) -> Self :: LocalDefIds ;
Original file line number Diff line number Diff line change 1+ //@ edition: 2024
2+
3+ // Regression test for #140583. We want to borrowck nested
4+ // bodies even if they are in dead code. While not necessary for
5+ // soundness, it is desirable to error in such cases.
6+
7+ fn main ( ) {
8+ return ;
9+ |x : & str | -> & ' static str { x } ;
10+ //~^ ERROR lifetime may not live long enough
11+ || {
12+ || {
13+ let temp = 1 ;
14+ let p: & ' static u32 = & temp;
15+ //~^ ERROR `temp` does not live long enough
16+ } ;
17+ } ;
18+ const {
19+ let temp = 1 ;
20+ let p: & ' static u32 = & temp;
21+ //~^ ERROR `temp` does not live long enough
22+ } ;
23+ async {
24+ let temp = 1 ;
25+ let p: & ' static u32 = & temp;
26+ //~^ ERROR `temp` does not live long enough
27+ } ;
28+ }
You can’t perform that action at this time.
0 commit comments