@@ -21,6 +21,7 @@ use std::cell::RefCell;
2121use std:: marker:: PhantomData ;
2222use std:: ops:: { ControlFlow , Deref } ;
2323
24+ use root_cx:: BorrowCheckRootCtxt ;
2425use rustc_abi:: FieldIdx ;
2526use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
2627use rustc_data_structures:: graph:: dominators:: Dominators ;
@@ -45,7 +46,7 @@ use rustc_mir_dataflow::move_paths::{
4546} ;
4647use rustc_mir_dataflow:: { Analysis , EntryStates , Results , ResultsVisitor , visit_results} ;
4748use rustc_session:: lint:: builtin:: { TAIL_EXPR_DROP_ORDER , UNUSED_MUT } ;
48- use rustc_span:: { Span , Symbol } ;
49+ use rustc_span:: { ErrorGuaranteed , Span , Symbol } ;
4950use smallvec:: SmallVec ;
5051use tracing:: { debug, instrument} ;
5152
@@ -73,14 +74,14 @@ mod def_use;
7374mod diagnostics;
7475mod member_constraints;
7576mod nll;
76- mod opaque_types;
7777mod path_utils;
7878mod place_ext;
7979mod places_conflict;
8080mod polonius;
8181mod prefixes;
8282mod region_infer;
8383mod renumber;
84+ mod root_cx;
8485mod session_diagnostics;
8586mod type_check;
8687mod universal_regions;
@@ -102,44 +103,64 @@ pub fn provide(providers: &mut Providers) {
102103 * providers = Providers { mir_borrowck, ..* providers } ;
103104}
104105
105- fn mir_borrowck ( tcx : TyCtxt < ' _ > , def : LocalDefId ) -> & BorrowCheckResult < ' _ > {
106+ /// Provider for `query mir_borrowck`. Similar to `typeck`, this must
107+ /// only be called for typeck roots which will then borrowck all
108+ /// nested bodies as well.
109+ fn mir_borrowck (
110+ tcx : TyCtxt < ' _ > ,
111+ def : LocalDefId ,
112+ ) -> Result < & ConcreteOpaqueTypes < ' _ > , ErrorGuaranteed > {
113+ assert ! ( !tcx. is_typeck_child( def. to_def_id( ) ) ) ;
106114 let ( input_body, _) = tcx. mir_promoted ( def) ;
115+ debug ! ( "run query mir_borrowck: {}" , tcx. def_path_str( def) ) ;
116+
107117 let input_body: & Body < ' _ > = & input_body. borrow ( ) ;
108- if input_body. should_skip ( ) || input_body. tainted_by_errors . is_some ( ) {
109- debug ! ( "Skipping borrowck because of injected body or tainted body" ) ;
110- // Let's make up a borrowck result! Fun times!
111- let result = BorrowCheckResult {
112- concrete_opaque_types : FxIndexMap :: default ( ) ,
113- closure_requirements : None ,
114- used_mut_upvars : SmallVec :: new ( ) ,
115- tainted_by_errors : input_body. tainted_by_errors ,
116- } ;
117- return tcx. arena . alloc ( result) ;
118+ if let Some ( guar) = input_body. tainted_by_errors {
119+ debug ! ( "Skipping borrowck because of tainted body" ) ;
120+ Err ( guar)
121+ } else if input_body. should_skip ( ) {
122+ debug ! ( "Skipping borrowck because of injected body" ) ;
123+ let opaque_types = ConcreteOpaqueTypes ( Default :: default ( ) ) ;
124+ Ok ( tcx. arena . alloc ( opaque_types) )
125+ } else {
126+ let mut root_cx = BorrowCheckRootCtxt :: new ( tcx, def) ;
127+ let PropagatedBorrowCheckResults { closure_requirements, used_mut_upvars } =
128+ do_mir_borrowck ( & mut root_cx, def, None ) . 0 ;
129+ debug_assert ! ( closure_requirements. is_none( ) ) ;
130+ debug_assert ! ( used_mut_upvars. is_empty( ) ) ;
131+ root_cx. finalize ( )
118132 }
133+ }
119134
120- let borrowck_result = do_mir_borrowck ( tcx, def, None ) . 0 ;
121- debug ! ( "mir_borrowck done" ) ;
122-
123- tcx. arena . alloc ( borrowck_result)
135+ /// Data propagated to the typeck parent by nested items.
136+ /// This should always be empty for the typeck root.
137+ #[ derive( Debug ) ]
138+ struct PropagatedBorrowCheckResults < ' tcx > {
139+ closure_requirements : Option < ClosureRegionRequirements < ' tcx > > ,
140+ used_mut_upvars : SmallVec < [ FieldIdx ; 8 ] > ,
124141}
125142
126143/// Perform the actual borrow checking.
127144///
128145/// Use `consumer_options: None` for the default behavior of returning
129- /// [`BorrowCheckResult`] only. Otherwise, return [`BodyWithBorrowckFacts`] according
130- /// to the given [`ConsumerOptions`].
131- #[ instrument( skip( tcx) , level = "debug" ) ]
146+ /// [`PropagatedBorrowCheckResults`] only. Otherwise, return [`BodyWithBorrowckFacts`]
147+ /// according to the given [`ConsumerOptions`].
148+ ///
149+ /// For nested bodies this should only be called through `root_cx.get_or_insert_nested`.
150+ #[ instrument( skip( root_cx) , level = "debug" ) ]
132151fn do_mir_borrowck < ' tcx > (
133- tcx : TyCtxt < ' tcx > ,
152+ root_cx : & mut BorrowCheckRootCtxt < ' tcx > ,
134153 def : LocalDefId ,
135154 consumer_options : Option < ConsumerOptions > ,
136- ) -> ( BorrowCheckResult < ' tcx > , Option < Box < BodyWithBorrowckFacts < ' tcx > > > ) {
155+ ) -> ( PropagatedBorrowCheckResults < ' tcx > , Option < Box < BodyWithBorrowckFacts < ' tcx > > > ) {
156+ let tcx = root_cx. tcx ;
137157 let infcx = BorrowckInferCtxt :: new ( tcx, def) ;
138158 let ( input_body, promoted) = tcx. mir_promoted ( def) ;
139159 let input_body: & Body < ' _ > = & input_body. borrow ( ) ;
140160 let input_promoted: & IndexSlice < _ , _ > = & promoted. borrow ( ) ;
141161 if let Some ( e) = input_body. tainted_by_errors {
142162 infcx. set_tainted_by_errors ( e) ;
163+ root_cx. set_tainted_by_errors ( e) ;
143164 }
144165
145166 let mut local_names = IndexVec :: from_elem ( None , & input_body. local_decls ) ;
@@ -185,13 +206,13 @@ fn do_mir_borrowck<'tcx>(
185206 // Compute non-lexical lifetimes.
186207 let nll:: NllOutput {
187208 regioncx,
188- concrete_opaque_types,
189209 polonius_input,
190210 polonius_output,
191211 opt_closure_req,
192212 nll_errors,
193213 polonius_diagnostics,
194214 } = nll:: compute_regions (
215+ root_cx,
195216 & infcx,
196217 free_regions,
197218 body,
@@ -210,26 +231,19 @@ fn do_mir_borrowck<'tcx>(
210231 // We also have a `#[rustc_regions]` annotation that causes us to dump
211232 // information.
212233 let diags_buffer = & mut BorrowckDiagnosticsBuffer :: default ( ) ;
213- nll:: dump_annotation (
214- & infcx,
215- body,
216- & regioncx,
217- & opt_closure_req,
218- & concrete_opaque_types,
219- diags_buffer,
220- ) ;
234+ nll:: dump_annotation ( & infcx, body, & regioncx, & opt_closure_req, diags_buffer) ;
221235
222236 let movable_coroutine =
223- // The first argument is the coroutine type passed by value
224- if let Some ( local) = body. local_decls . raw . get ( 1 )
225- // Get the interior types and args which typeck computed
226- && let ty:: Coroutine ( def_id, _) = * local. ty . kind ( )
227- && tcx. coroutine_movability ( def_id) == hir:: Movability :: Movable
228- {
229- true
230- } else {
231- false
232- } ;
237+ // The first argument is the coroutine type passed by value
238+ if let Some ( local) = body. local_decls . raw . get ( 1 )
239+ // Get the interior types and args which typeck computed
240+ && let ty:: Coroutine ( def_id, _) = * local. ty . kind ( )
241+ && tcx. coroutine_movability ( def_id) == hir:: Movability :: Movable
242+ {
243+ true
244+ } else {
245+ false
246+ } ;
233247
234248 // While promoteds should mostly be correct by construction, we need to check them for
235249 // invalid moves to detect moving out of arrays:`struct S; fn main() { &([S][0]); }`.
@@ -240,6 +254,7 @@ fn do_mir_borrowck<'tcx>(
240254 // this check out of `MirBorrowckCtxt`, actually doing so is far from trivial.
241255 let move_data = MoveData :: gather_moves ( promoted_body, tcx, |_| true ) ;
242256 let mut promoted_mbcx = MirBorrowckCtxt {
257+ root_cx,
243258 infcx : & infcx,
244259 body : promoted_body,
245260 move_data : & move_data,
@@ -280,6 +295,7 @@ fn do_mir_borrowck<'tcx>(
280295 }
281296
282297 let mut mbcx = MirBorrowckCtxt {
298+ root_cx,
283299 infcx : & infcx,
284300 body,
285301 move_data : & move_data,
@@ -347,13 +363,13 @@ fn do_mir_borrowck<'tcx>(
347363
348364 debug ! ( "mbcx.used_mut: {:?}" , mbcx. used_mut) ;
349365 mbcx. lint_unused_mut ( ) ;
350- let tainted_by_errors = mbcx. emit_errors ( ) ;
366+ if let Some ( guar) = mbcx. emit_errors ( ) {
367+ mbcx. root_cx . set_tainted_by_errors ( guar) ;
368+ }
351369
352- let result = BorrowCheckResult {
353- concrete_opaque_types : concrete_opaque_types. into_inner ( ) ,
370+ let result = PropagatedBorrowCheckResults {
354371 closure_requirements : opt_closure_req,
355372 used_mut_upvars : mbcx. used_mut_upvars ,
356- tainted_by_errors,
357373 } ;
358374
359375 let body_with_facts = if consumer_options. is_some ( ) {
@@ -488,6 +504,7 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
488504}
489505
490506struct MirBorrowckCtxt < ' a , ' infcx , ' tcx > {
507+ root_cx : & ' a mut BorrowCheckRootCtxt < ' tcx > ,
491508 infcx : & ' infcx BorrowckInferCtxt < ' tcx > ,
492509 body : & ' a Body < ' tcx > ,
493510 move_data : & ' a MoveData < ' tcx > ,
@@ -1361,11 +1378,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
13611378 | AggregateKind :: CoroutineClosure ( def_id, _)
13621379 | AggregateKind :: Coroutine ( def_id, _) => {
13631380 let def_id = def_id. expect_local ( ) ;
1364- let BorrowCheckResult { used_mut_upvars, .. } =
1365- self . infcx . tcx . mir_borrowck ( def_id) ;
1381+ let used_mut_upvars = self . root_cx . used_mut_upvars ( def_id) ;
13661382 debug ! ( "{:?} used_mut_upvars={:?}" , def_id, used_mut_upvars) ;
1367- for field in used_mut_upvars {
1368- self . propagate_closure_used_mut_upvar ( & operands[ * field] ) ;
1383+ // FIXME: We're cloning the `SmallVec` here to avoid borrowing `root_cx`
1384+ // when calling `propagate_closure_used_mut_upvar`. This should ideally
1385+ // be unnecessary.
1386+ for field in used_mut_upvars. clone ( ) {
1387+ self . propagate_closure_used_mut_upvar ( & operands[ field] ) ;
13691388 }
13701389 }
13711390 AggregateKind :: Adt ( ..)
0 commit comments