11//! This query borrow-checks the MIR to (further) ensure it is not broken.
22
33// tidy-alphabetical-start
4- #![ allow( internal_features) ]
4+ #![ allow( internal_features, unused ) ]
55#![ cfg_attr( doc, recursion_limit = "256" ) ] // FIXME(nnethercote): will be removed by #124141
66#![ doc( rust_logo) ]
77#![ feature( assert_matches) ]
@@ -21,15 +21,18 @@ use std::borrow::Cow;
2121use std:: cell:: RefCell ;
2222use std:: marker:: PhantomData ;
2323use std:: ops:: { ControlFlow , Deref } ;
24+ use std:: rc:: Rc ;
2425
26+ use nll:: YieldComputeRegions ;
27+ use region_infer:: opaque_types:: { DeferredOpaqueTypeError , handle_opaque_type_uses} ;
2528use root_cx:: BorrowCheckRootCtxt ;
2629use rustc_abi:: FieldIdx ;
2730use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
2831use rustc_data_structures:: graph:: dominators:: Dominators ;
2932use rustc_errors:: LintDiagnostic ;
3033use rustc_hir as hir;
3134use rustc_hir:: CRATE_HIR_ID ;
32- use rustc_hir:: def_id:: LocalDefId ;
35+ use rustc_hir:: def_id:: { DefId , LocalDefId } ;
3336use rustc_index:: bit_set:: { DenseBitSet , MixedBitSet } ;
3437use rustc_index:: { IndexSlice , IndexVec } ;
3538use rustc_infer:: infer:: {
@@ -52,6 +55,7 @@ use rustc_session::lint::builtin::{TAIL_EXPR_DROP_ORDER, UNUSED_MUT};
5255use rustc_span:: { ErrorGuaranteed , Span , Symbol } ;
5356use smallvec:: SmallVec ;
5457use tracing:: { debug, instrument} ;
58+ use type_check:: Locations ;
5559
5660use crate :: borrow_set:: { BorrowData , BorrowSet } ;
5761use crate :: consumers:: { BodyWithBorrowckFacts , ConsumerOptions } ;
@@ -126,11 +130,7 @@ fn mir_borrowck(
126130 Ok ( tcx. arena . alloc ( opaque_types) )
127131 } else {
128132 let mut root_cx = BorrowCheckRootCtxt :: new ( tcx, def) ;
129- let PropagatedBorrowCheckResults { closure_requirements, used_mut_upvars } =
130- do_mir_borrowck ( & mut root_cx, def, None ) . 0 ;
131- debug_assert ! ( closure_requirements. is_none( ) ) ;
132- debug_assert ! ( used_mut_upvars. is_empty( ) ) ;
133- root_cx. finalize ( )
133+ root_cx. borrowck_root ( None ) . 0
134134 }
135135}
136136
@@ -142,6 +142,8 @@ struct PropagatedBorrowCheckResults<'tcx> {
142142 used_mut_upvars : SmallVec < [ FieldIdx ; 8 ] > ,
143143}
144144
145+ type DeferredClosureRequirements < ' tcx > = Vec < ( LocalDefId , ty:: GenericArgsRef < ' tcx > , Locations ) > ;
146+
145147/// After we borrow check a closure, we are left with various
146148/// requirements that we have inferred between the free regions that
147149/// appear in the closure's signature or on its field types. These
@@ -280,6 +282,17 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
280282 }
281283}
282284
285+ struct YieldDoMirBorrowck < ' tcx > {
286+ infcx : BorrowckInferCtxt < ' tcx > ,
287+ body_owned : Body < ' tcx > ,
288+ promoted : IndexVec < Promoted , Body < ' tcx > > ,
289+ move_data : MoveData < ' tcx > ,
290+ locals_are_invalidated_at_exit : bool ,
291+ borrow_set : BorrowSet < ' tcx > ,
292+ location_table : PoloniusLocationTable ,
293+ yield_compute_regions : YieldComputeRegions < ' tcx > ,
294+ }
295+
283296/// Perform the actual borrow checking.
284297///
285298/// Use `consumer_options: None` for the default behavior of returning
@@ -288,11 +301,11 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
288301///
289302/// For nested bodies this should only be called through `root_cx.get_or_insert_nested`.
290303#[ instrument( skip( root_cx) , level = "debug" ) ]
291- fn do_mir_borrowck < ' tcx > (
304+ fn start_do_mir_borrowck < ' tcx > (
292305 root_cx : & mut BorrowCheckRootCtxt < ' tcx > ,
293306 def : LocalDefId ,
294307 consumer_options : Option < ConsumerOptions > ,
295- ) -> ( PropagatedBorrowCheckResults < ' tcx > , Option < Box < BodyWithBorrowckFacts < ' tcx > > > ) {
308+ ) -> YieldDoMirBorrowck < ' tcx > {
296309 let tcx = root_cx. tcx ;
297310 let infcx = BorrowckInferCtxt :: new ( tcx, def) ;
298311 let ( input_body, promoted) = tcx. mir_promoted ( def) ;
@@ -303,33 +316,13 @@ fn do_mir_borrowck<'tcx>(
303316 root_cx. set_tainted_by_errors ( e) ;
304317 }
305318
306- let mut local_names = IndexVec :: from_elem ( None , & input_body. local_decls ) ;
307- for var_debug_info in & input_body. var_debug_info {
308- if let VarDebugInfoContents :: Place ( place) = var_debug_info. value {
309- if let Some ( local) = place. as_local ( ) {
310- if let Some ( prev_name) = local_names[ local]
311- && var_debug_info. name != prev_name
312- {
313- span_bug ! (
314- var_debug_info. source_info. span,
315- "local {:?} has many names (`{}` vs `{}`)" ,
316- local,
317- prev_name,
318- var_debug_info. name
319- ) ;
320- }
321- local_names[ local] = Some ( var_debug_info. name ) ;
322- }
323- }
324- }
325-
326319 // Replace all regions with fresh inference variables. This
327320 // requires first making our own copy of the MIR. This copy will
328321 // be modified (in place) to contain non-lexical lifetimes. It
329322 // will have a lifetime tied to the inference context.
330323 let mut body_owned = input_body. clone ( ) ;
331324 let mut promoted = input_promoted. to_owned ( ) ;
332- let free_regions = nll:: replace_regions_in_mir ( & infcx, & mut body_owned, & mut promoted) ;
325+ let universal_regions = nll:: replace_regions_in_mir ( & infcx, & mut body_owned, & mut promoted) ;
333326 let body = & body_owned; // no further changes
334327
335328 let location_table = PoloniusLocationTable :: new ( body) ;
@@ -343,6 +336,50 @@ fn do_mir_borrowck<'tcx>(
343336 let locals_are_invalidated_at_exit = tcx. hir_body_owner_kind ( def) . is_fn_or_closure ( ) ;
344337 let borrow_set = BorrowSet :: build ( tcx, body, locals_are_invalidated_at_exit, & move_data) ;
345338
339+ let yield_compute_regions = nll:: compute_regions (
340+ root_cx,
341+ & infcx,
342+ universal_regions,
343+ body,
344+ & promoted,
345+ & location_table,
346+ flow_inits,
347+ & move_data,
348+ & borrow_set,
349+ consumer_options,
350+ ) ;
351+
352+ YieldDoMirBorrowck {
353+ infcx,
354+ body_owned,
355+ promoted,
356+ move_data,
357+ locals_are_invalidated_at_exit,
358+ borrow_set,
359+ location_table,
360+ yield_compute_regions,
361+ }
362+ }
363+
364+ fn resume_do_mir_borrowck < ' tcx > (
365+ root_cx : & mut BorrowCheckRootCtxt < ' tcx > ,
366+ def : LocalDefId ,
367+ consumer_options : Option < ConsumerOptions > ,
368+ YieldDoMirBorrowck {
369+ infcx,
370+ body_owned,
371+ promoted,
372+ move_data,
373+ locals_are_invalidated_at_exit,
374+ borrow_set,
375+ location_table,
376+ yield_compute_regions,
377+ } : YieldDoMirBorrowck < ' tcx > ,
378+ ) -> ( PropagatedBorrowCheckResults < ' tcx > , Option < Box < BodyWithBorrowckFacts < ' tcx > > > ) {
379+ assert ! ( !infcx. has_opaque_types_in_storage( ) ) ;
380+ let tcx = infcx. tcx ;
381+ let body = & body_owned;
382+
346383 // Compute non-lexical lifetimes.
347384 let nll:: NllOutput {
348385 regioncx,
@@ -351,17 +388,15 @@ fn do_mir_borrowck<'tcx>(
351388 opt_closure_req,
352389 nll_errors,
353390 polonius_diagnostics,
354- } = nll:: compute_regions (
391+ } = nll:: resume_compute_regions (
355392 root_cx,
356393 & infcx,
357- free_regions,
358394 body,
359- & promoted,
360395 & location_table,
361- flow_inits,
362396 & move_data,
363397 & borrow_set,
364398 consumer_options,
399+ yield_compute_regions,
365400 ) ;
366401
367402 // Dump MIR results into a file, if that is enabled. This lets us
@@ -376,14 +411,14 @@ fn do_mir_borrowck<'tcx>(
376411 let movable_coroutine =
377412 // The first argument is the coroutine type passed by value
378413 if let Some ( local) = body. local_decls . raw . get ( 1 )
379- // Get the interior types and args which typeck computed
380- && let ty:: Coroutine ( def_id, _) = * local. ty . kind ( )
381- && tcx. coroutine_movability ( def_id) == hir:: Movability :: Movable
382- {
383- true
384- } else {
385- false
386- } ;
414+ // Get the interior types and args which typeck computed
415+ && let ty:: Coroutine ( def_id, _) = * local. ty . kind ( )
416+ && tcx. coroutine_movability ( def_id) == hir:: Movability :: Movable
417+ {
418+ true
419+ } else {
420+ false
421+ } ;
387422
388423 // While promoteds should mostly be correct by construction, we need to check them for
389424 // invalid moves to detect moving out of arrays:`struct S; fn main() { &([S][0]); }`.
@@ -434,6 +469,26 @@ fn do_mir_borrowck<'tcx>(
434469 promoted_mbcx. report_move_errors ( ) ;
435470 }
436471
472+ let mut local_names = IndexVec :: from_elem ( None , & body. local_decls ) ;
473+ for var_debug_info in & body. var_debug_info {
474+ if let VarDebugInfoContents :: Place ( place) = var_debug_info. value {
475+ if let Some ( local) = place. as_local ( ) {
476+ if let Some ( prev_name) = local_names[ local]
477+ && var_debug_info. name != prev_name
478+ {
479+ span_bug ! (
480+ var_debug_info. source_info. span,
481+ "local {:?} has many names (`{}` vs `{}`)" ,
482+ local,
483+ prev_name,
484+ var_debug_info. name
485+ ) ;
486+ }
487+ local_names[ local] = Some ( var_debug_info. name ) ;
488+ }
489+ }
490+ }
491+
437492 let mut mbcx = MirBorrowckCtxt {
438493 root_cx,
439494 infcx : & infcx,
0 commit comments