1
1
//! This query borrow-checks the MIR to (further) ensure it is not broken.
2
2
3
3
// tidy-alphabetical-start
4
- #![ allow( internal_features) ]
4
+ #![ allow( internal_features, unused ) ]
5
5
#![ cfg_attr( doc, recursion_limit = "256" ) ] // FIXME(nnethercote): will be removed by #124141
6
6
#![ doc( rust_logo) ]
7
7
#![ feature( assert_matches) ]
@@ -21,15 +21,18 @@ use std::borrow::Cow;
21
21
use std:: cell:: RefCell ;
22
22
use std:: marker:: PhantomData ;
23
23
use std:: ops:: { ControlFlow , Deref } ;
24
+ use std:: rc:: Rc ;
24
25
26
+ use nll:: YieldComputeRegions ;
27
+ use region_infer:: opaque_types:: { DeferredOpaqueTypeError , handle_opaque_type_uses} ;
25
28
use root_cx:: BorrowCheckRootCtxt ;
26
29
use rustc_abi:: FieldIdx ;
27
30
use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
28
31
use rustc_data_structures:: graph:: dominators:: Dominators ;
29
32
use rustc_errors:: LintDiagnostic ;
30
33
use rustc_hir as hir;
31
34
use rustc_hir:: CRATE_HIR_ID ;
32
- use rustc_hir:: def_id:: LocalDefId ;
35
+ use rustc_hir:: def_id:: { DefId , LocalDefId } ;
33
36
use rustc_index:: bit_set:: { DenseBitSet , MixedBitSet } ;
34
37
use rustc_index:: { IndexSlice , IndexVec } ;
35
38
use rustc_infer:: infer:: {
@@ -52,6 +55,7 @@ use rustc_session::lint::builtin::{TAIL_EXPR_DROP_ORDER, UNUSED_MUT};
52
55
use rustc_span:: { ErrorGuaranteed , Span , Symbol } ;
53
56
use smallvec:: SmallVec ;
54
57
use tracing:: { debug, instrument} ;
58
+ use type_check:: Locations ;
55
59
56
60
use crate :: borrow_set:: { BorrowData , BorrowSet } ;
57
61
use crate :: consumers:: { BodyWithBorrowckFacts , ConsumerOptions } ;
@@ -126,11 +130,7 @@ fn mir_borrowck(
126
130
Ok ( tcx. arena . alloc ( opaque_types) )
127
131
} else {
128
132
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
134
134
}
135
135
}
136
136
@@ -142,6 +142,8 @@ struct PropagatedBorrowCheckResults<'tcx> {
142
142
used_mut_upvars : SmallVec < [ FieldIdx ; 8 ] > ,
143
143
}
144
144
145
+ type DeferredClosureRequirements < ' tcx > = Vec < ( LocalDefId , ty:: GenericArgsRef < ' tcx > , Locations ) > ;
146
+
145
147
/// After we borrow check a closure, we are left with various
146
148
/// requirements that we have inferred between the free regions that
147
149
/// appear in the closure's signature or on its field types. These
@@ -280,6 +282,17 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
280
282
}
281
283
}
282
284
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
+
283
296
/// Perform the actual borrow checking.
284
297
///
285
298
/// Use `consumer_options: None` for the default behavior of returning
@@ -288,11 +301,11 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
288
301
///
289
302
/// For nested bodies this should only be called through `root_cx.get_or_insert_nested`.
290
303
#[ instrument( skip( root_cx) , level = "debug" ) ]
291
- fn do_mir_borrowck < ' tcx > (
304
+ fn start_do_mir_borrowck < ' tcx > (
292
305
root_cx : & mut BorrowCheckRootCtxt < ' tcx > ,
293
306
def : LocalDefId ,
294
307
consumer_options : Option < ConsumerOptions > ,
295
- ) -> ( PropagatedBorrowCheckResults < ' tcx > , Option < Box < BodyWithBorrowckFacts < ' tcx > > > ) {
308
+ ) -> YieldDoMirBorrowck < ' tcx > {
296
309
let tcx = root_cx. tcx ;
297
310
let infcx = BorrowckInferCtxt :: new ( tcx, def) ;
298
311
let ( input_body, promoted) = tcx. mir_promoted ( def) ;
@@ -303,33 +316,13 @@ fn do_mir_borrowck<'tcx>(
303
316
root_cx. set_tainted_by_errors ( e) ;
304
317
}
305
318
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
-
326
319
// Replace all regions with fresh inference variables. This
327
320
// requires first making our own copy of the MIR. This copy will
328
321
// be modified (in place) to contain non-lexical lifetimes. It
329
322
// will have a lifetime tied to the inference context.
330
323
let mut body_owned = input_body. clone ( ) ;
331
324
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) ;
333
326
let body = & body_owned; // no further changes
334
327
335
328
let location_table = PoloniusLocationTable :: new ( body) ;
@@ -343,6 +336,50 @@ fn do_mir_borrowck<'tcx>(
343
336
let locals_are_invalidated_at_exit = tcx. hir_body_owner_kind ( def) . is_fn_or_closure ( ) ;
344
337
let borrow_set = BorrowSet :: build ( tcx, body, locals_are_invalidated_at_exit, & move_data) ;
345
338
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
+
346
383
// Compute non-lexical lifetimes.
347
384
let nll:: NllOutput {
348
385
regioncx,
@@ -351,17 +388,15 @@ fn do_mir_borrowck<'tcx>(
351
388
opt_closure_req,
352
389
nll_errors,
353
390
polonius_diagnostics,
354
- } = nll:: compute_regions (
391
+ } = nll:: resume_compute_regions (
355
392
root_cx,
356
393
& infcx,
357
- free_regions,
358
394
body,
359
- & promoted,
360
395
& location_table,
361
- flow_inits,
362
396
& move_data,
363
397
& borrow_set,
364
398
consumer_options,
399
+ yield_compute_regions,
365
400
) ;
366
401
367
402
// Dump MIR results into a file, if that is enabled. This lets us
@@ -376,14 +411,14 @@ fn do_mir_borrowck<'tcx>(
376
411
let movable_coroutine =
377
412
// The first argument is the coroutine type passed by value
378
413
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
+ } ;
387
422
388
423
// While promoteds should mostly be correct by construction, we need to check them for
389
424
// invalid moves to detect moving out of arrays:`struct S; fn main() { &([S][0]); }`.
@@ -434,6 +469,26 @@ fn do_mir_borrowck<'tcx>(
434
469
promoted_mbcx. report_move_errors ( ) ;
435
470
}
436
471
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
+
437
492
let mut mbcx = MirBorrowckCtxt {
438
493
root_cx,
439
494
infcx : & infcx,
0 commit comments