@@ -21,6 +21,7 @@ use std::cell::RefCell;
21
21
use std:: marker:: PhantomData ;
22
22
use std:: ops:: { ControlFlow , Deref } ;
23
23
24
+ use root_cx:: BorrowCheckRootCtxt ;
24
25
use rustc_abi:: FieldIdx ;
25
26
use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
26
27
use rustc_data_structures:: graph:: dominators:: Dominators ;
@@ -45,7 +46,7 @@ use rustc_mir_dataflow::move_paths::{
45
46
} ;
46
47
use rustc_mir_dataflow:: { Analysis , EntryStates , Results , ResultsVisitor , visit_results} ;
47
48
use rustc_session:: lint:: builtin:: { TAIL_EXPR_DROP_ORDER , UNUSED_MUT } ;
48
- use rustc_span:: { Span , Symbol } ;
49
+ use rustc_span:: { ErrorGuaranteed , Span , Symbol } ;
49
50
use smallvec:: SmallVec ;
50
51
use tracing:: { debug, instrument} ;
51
52
@@ -73,14 +74,14 @@ mod def_use;
73
74
mod diagnostics;
74
75
mod member_constraints;
75
76
mod nll;
76
- mod opaque_types;
77
77
mod path_utils;
78
78
mod place_ext;
79
79
mod places_conflict;
80
80
mod polonius;
81
81
mod prefixes;
82
82
mod region_infer;
83
83
mod renumber;
84
+ mod root_cx;
84
85
mod session_diagnostics;
85
86
mod type_check;
86
87
mod universal_regions;
@@ -102,44 +103,64 @@ pub fn provide(providers: &mut Providers) {
102
103
* providers = Providers { mir_borrowck, ..* providers } ;
103
104
}
104
105
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( ) ) ) ;
106
114
let ( input_body, _) = tcx. mir_promoted ( def) ;
115
+ debug ! ( "run query mir_borrowck: {}" , tcx. def_path_str( def) ) ;
116
+
107
117
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 ( )
118
132
}
133
+ }
119
134
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 ] > ,
124
141
}
125
142
126
143
/// Perform the actual borrow checking.
127
144
///
128
145
/// 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" ) ]
132
151
fn do_mir_borrowck < ' tcx > (
133
- tcx : TyCtxt < ' tcx > ,
152
+ root_cx : & mut BorrowCheckRootCtxt < ' tcx > ,
134
153
def : LocalDefId ,
135
154
consumer_options : Option < ConsumerOptions > ,
136
- ) -> ( BorrowCheckResult < ' tcx > , Option < Box < BodyWithBorrowckFacts < ' tcx > > > ) {
155
+ ) -> ( PropagatedBorrowCheckResults < ' tcx > , Option < Box < BodyWithBorrowckFacts < ' tcx > > > ) {
156
+ let tcx = root_cx. tcx ;
137
157
let infcx = BorrowckInferCtxt :: new ( tcx, def) ;
138
158
let ( input_body, promoted) = tcx. mir_promoted ( def) ;
139
159
let input_body: & Body < ' _ > = & input_body. borrow ( ) ;
140
160
let input_promoted: & IndexSlice < _ , _ > = & promoted. borrow ( ) ;
141
161
if let Some ( e) = input_body. tainted_by_errors {
142
162
infcx. set_tainted_by_errors ( e) ;
163
+ root_cx. set_tainted_by_errors ( e) ;
143
164
}
144
165
145
166
let mut local_names = IndexVec :: from_elem ( None , & input_body. local_decls ) ;
@@ -191,13 +212,13 @@ fn do_mir_borrowck<'tcx>(
191
212
// Compute non-lexical lifetimes.
192
213
let nll:: NllOutput {
193
214
regioncx,
194
- concrete_opaque_types,
195
215
polonius_input,
196
216
polonius_output,
197
217
opt_closure_req,
198
218
nll_errors,
199
219
polonius_diagnostics,
200
220
} = nll:: compute_regions (
221
+ root_cx,
201
222
& infcx,
202
223
free_regions,
203
224
body,
@@ -216,26 +237,19 @@ fn do_mir_borrowck<'tcx>(
216
237
// We also have a `#[rustc_regions]` annotation that causes us to dump
217
238
// information.
218
239
let diags_buffer = & mut BorrowckDiagnosticsBuffer :: default ( ) ;
219
- nll:: dump_annotation (
220
- & infcx,
221
- body,
222
- & regioncx,
223
- & opt_closure_req,
224
- & concrete_opaque_types,
225
- diags_buffer,
226
- ) ;
240
+ nll:: dump_annotation ( & infcx, body, & regioncx, & opt_closure_req, diags_buffer) ;
227
241
228
242
let movable_coroutine =
229
- // The first argument is the coroutine type passed by value
230
- if let Some ( local) = body. local_decls . raw . get ( 1 )
231
- // Get the interior types and args which typeck computed
232
- && let ty:: Coroutine ( def_id, _) = * local. ty . kind ( )
233
- && tcx. coroutine_movability ( def_id) == hir:: Movability :: Movable
234
- {
235
- true
236
- } else {
237
- false
238
- } ;
243
+ // The first argument is the coroutine type passed by value
244
+ if let Some ( local) = body. local_decls . raw . get ( 1 )
245
+ // Get the interior types and args which typeck computed
246
+ && let ty:: Coroutine ( def_id, _) = * local. ty . kind ( )
247
+ && tcx. coroutine_movability ( def_id) == hir:: Movability :: Movable
248
+ {
249
+ true
250
+ } else {
251
+ false
252
+ } ;
239
253
240
254
// While promoteds should mostly be correct by construction, we need to check them for
241
255
// invalid moves to detect moving out of arrays:`struct S; fn main() { &([S][0]); }`.
@@ -246,6 +260,7 @@ fn do_mir_borrowck<'tcx>(
246
260
// this check out of `MirBorrowckCtxt`, actually doing so is far from trivial.
247
261
let move_data = MoveData :: gather_moves ( promoted_body, tcx, |_| true ) ;
248
262
let mut promoted_mbcx = MirBorrowckCtxt {
263
+ root_cx,
249
264
infcx : & infcx,
250
265
body : promoted_body,
251
266
move_data : & move_data,
@@ -286,6 +301,7 @@ fn do_mir_borrowck<'tcx>(
286
301
}
287
302
288
303
let mut mbcx = MirBorrowckCtxt {
304
+ root_cx,
289
305
infcx : & infcx,
290
306
body,
291
307
move_data : & move_data,
@@ -353,13 +369,13 @@ fn do_mir_borrowck<'tcx>(
353
369
354
370
debug ! ( "mbcx.used_mut: {:?}" , mbcx. used_mut) ;
355
371
mbcx. lint_unused_mut ( ) ;
356
- let tainted_by_errors = mbcx. emit_errors ( ) ;
372
+ if let Some ( guar) = mbcx. emit_errors ( ) {
373
+ mbcx. root_cx . set_tainted_by_errors ( guar) ;
374
+ }
357
375
358
- let result = BorrowCheckResult {
359
- concrete_opaque_types : concrete_opaque_types. into_inner ( ) ,
376
+ let result = PropagatedBorrowCheckResults {
360
377
closure_requirements : opt_closure_req,
361
378
used_mut_upvars : mbcx. used_mut_upvars ,
362
- tainted_by_errors,
363
379
} ;
364
380
365
381
let body_with_facts = if consumer_options. is_some ( ) {
@@ -512,6 +528,7 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
512
528
}
513
529
514
530
struct MirBorrowckCtxt < ' a , ' infcx , ' tcx > {
531
+ root_cx : & ' a mut BorrowCheckRootCtxt < ' tcx > ,
515
532
infcx : & ' infcx BorrowckInferCtxt < ' tcx > ,
516
533
body : & ' a Body < ' tcx > ,
517
534
move_data : & ' a MoveData < ' tcx > ,
@@ -1385,11 +1402,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
1385
1402
| AggregateKind :: CoroutineClosure ( def_id, _)
1386
1403
| AggregateKind :: Coroutine ( def_id, _) => {
1387
1404
let def_id = def_id. expect_local ( ) ;
1388
- let BorrowCheckResult { used_mut_upvars, .. } =
1389
- self . infcx . tcx . mir_borrowck ( def_id) ;
1405
+ let used_mut_upvars = self . root_cx . used_mut_upvars ( def_id) ;
1390
1406
debug ! ( "{:?} used_mut_upvars={:?}" , def_id, used_mut_upvars) ;
1391
- for field in used_mut_upvars {
1392
- self . propagate_closure_used_mut_upvar ( & operands[ * field] ) ;
1407
+ // FIXME: We're cloning the `SmallVec` here to avoid borrowing `root_cx`
1408
+ // when calling `propagate_closure_used_mut_upvar`. This should ideally
1409
+ // be unnecessary.
1410
+ for field in used_mut_upvars. clone ( ) {
1411
+ self . propagate_closure_used_mut_upvar ( & operands[ field] ) ;
1393
1412
}
1394
1413
}
1395
1414
AggregateKind :: Adt ( ..)
0 commit comments