@@ -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,57 @@ 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
+ fn mir_borrowck (
107
+ tcx : TyCtxt < ' _ > ,
108
+ def : LocalDefId ,
109
+ ) -> Result < & ConcreteOpaqueTypes < ' _ > , ErrorGuaranteed > {
110
+ assert ! ( !tcx. is_typeck_child( def. to_def_id( ) ) ) ;
106
111
let ( input_body, _) = tcx. mir_promoted ( def) ;
112
+ debug ! ( "run query mir_borrowck: {}" , tcx. def_path_str( def) ) ;
113
+
107
114
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) ;
115
+ if let Some ( guar) = input_body. tainted_by_errors {
116
+ debug ! ( "Skipping borrowck because of tainted body" ) ;
117
+ Err ( guar)
118
+ } else if input_body. should_skip ( ) {
119
+ debug ! ( "Skipping borrowck because of injected body" ) ;
120
+ let opaque_types = ConcreteOpaqueTypes ( Default :: default ( ) ) ;
121
+ Ok ( tcx. arena . alloc ( opaque_types) )
122
+ } else {
123
+ let mut root_cx = BorrowCheckRootCtxt :: new ( tcx, def) ;
124
+ let BorrowCheckResult { closure_requirements, used_mut_upvars } =
125
+ do_mir_borrowck ( & mut root_cx, def, None ) . 0 ;
126
+ debug_assert ! ( closure_requirements. is_none( ) ) ;
127
+ debug_assert ! ( used_mut_upvars. is_empty( ) ) ;
128
+ root_cx. finalize ( )
118
129
}
130
+ }
119
131
120
- let borrowck_result = do_mir_borrowck ( tcx , def , None ) . 0 ;
121
- debug ! ( "mir_borrowck done" ) ;
122
-
123
- tcx . arena . alloc ( borrowck_result )
132
+ # [ derive ( Debug ) ]
133
+ struct BorrowCheckResult < ' tcx > {
134
+ closure_requirements : Option < ClosureRegionRequirements < ' tcx > > ,
135
+ used_mut_upvars : SmallVec < [ FieldIdx ; 8 ] > ,
124
136
}
125
137
126
138
/// Perform the actual borrow checking.
127
139
///
128
140
/// Use `consumer_options: None` for the default behavior of returning
129
141
/// [`BorrowCheckResult`] only. Otherwise, return [`BodyWithBorrowckFacts`] according
130
142
/// to the given [`ConsumerOptions`].
131
- #[ instrument( skip( tcx ) , level = "debug" ) ]
143
+ #[ instrument( skip( root_cx ) , level = "debug" ) ]
132
144
fn do_mir_borrowck < ' tcx > (
133
- tcx : TyCtxt < ' tcx > ,
145
+ root_cx : & mut BorrowCheckRootCtxt < ' tcx > ,
134
146
def : LocalDefId ,
135
147
consumer_options : Option < ConsumerOptions > ,
136
148
) -> ( BorrowCheckResult < ' tcx > , Option < Box < BodyWithBorrowckFacts < ' tcx > > > ) {
149
+ let tcx = root_cx. tcx ;
137
150
let infcx = BorrowckInferCtxt :: new ( tcx, def) ;
138
151
let ( input_body, promoted) = tcx. mir_promoted ( def) ;
139
152
let input_body: & Body < ' _ > = & input_body. borrow ( ) ;
140
153
let input_promoted: & IndexSlice < _ , _ > = & promoted. borrow ( ) ;
141
154
if let Some ( e) = input_body. tainted_by_errors {
142
155
infcx. set_tainted_by_errors ( e) ;
156
+ root_cx. set_tainted_by_errors ( e) ;
143
157
}
144
158
145
159
let mut local_names = IndexVec :: from_elem ( None , & input_body. local_decls ) ;
@@ -191,13 +205,13 @@ fn do_mir_borrowck<'tcx>(
191
205
// Compute non-lexical lifetimes.
192
206
let nll:: NllOutput {
193
207
regioncx,
194
- concrete_opaque_types,
195
208
polonius_input,
196
209
polonius_output,
197
210
opt_closure_req,
198
211
nll_errors,
199
212
polonius_diagnostics,
200
213
} = nll:: compute_regions (
214
+ root_cx,
201
215
& infcx,
202
216
free_regions,
203
217
body,
@@ -216,26 +230,19 @@ fn do_mir_borrowck<'tcx>(
216
230
// We also have a `#[rustc_regions]` annotation that causes us to dump
217
231
// information.
218
232
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
- ) ;
233
+ nll:: dump_annotation ( & infcx, body, & regioncx, & opt_closure_req, diags_buffer) ;
227
234
228
235
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
- } ;
236
+ // The first argument is the coroutine type passed by value
237
+ if let Some ( local) = body. local_decls . raw . get ( 1 )
238
+ // Get the interior types and args which typeck computed
239
+ && let ty:: Coroutine ( def_id, _) = * local. ty . kind ( )
240
+ && tcx. coroutine_movability ( def_id) == hir:: Movability :: Movable
241
+ {
242
+ true
243
+ } else {
244
+ false
245
+ } ;
239
246
240
247
// While promoteds should mostly be correct by construction, we need to check them for
241
248
// invalid moves to detect moving out of arrays:`struct S; fn main() { &([S][0]); }`.
@@ -246,6 +253,7 @@ fn do_mir_borrowck<'tcx>(
246
253
// this check out of `MirBorrowckCtxt`, actually doing so is far from trivial.
247
254
let move_data = MoveData :: gather_moves ( promoted_body, tcx, |_| true ) ;
248
255
let mut promoted_mbcx = MirBorrowckCtxt {
256
+ root_cx,
249
257
infcx : & infcx,
250
258
body : promoted_body,
251
259
move_data : & move_data,
@@ -286,6 +294,7 @@ fn do_mir_borrowck<'tcx>(
286
294
}
287
295
288
296
let mut mbcx = MirBorrowckCtxt {
297
+ root_cx,
289
298
infcx : & infcx,
290
299
body,
291
300
move_data : & move_data,
@@ -353,13 +362,13 @@ fn do_mir_borrowck<'tcx>(
353
362
354
363
debug ! ( "mbcx.used_mut: {:?}" , mbcx. used_mut) ;
355
364
mbcx. lint_unused_mut ( ) ;
356
- let tainted_by_errors = mbcx. emit_errors ( ) ;
365
+ if let Some ( guar) = mbcx. emit_errors ( ) {
366
+ mbcx. root_cx . set_tainted_by_errors ( guar) ;
367
+ }
357
368
358
369
let result = BorrowCheckResult {
359
- concrete_opaque_types : concrete_opaque_types. into_inner ( ) ,
360
370
closure_requirements : opt_closure_req,
361
371
used_mut_upvars : mbcx. used_mut_upvars ,
362
- tainted_by_errors,
363
372
} ;
364
373
365
374
let body_with_facts = if consumer_options. is_some ( ) {
@@ -512,6 +521,7 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
512
521
}
513
522
514
523
struct MirBorrowckCtxt < ' a , ' infcx , ' tcx > {
524
+ root_cx : & ' a mut BorrowCheckRootCtxt < ' tcx > ,
515
525
infcx : & ' infcx BorrowckInferCtxt < ' tcx > ,
516
526
body : & ' a Body < ' tcx > ,
517
527
move_data : & ' a MoveData < ' tcx > ,
@@ -1385,11 +1395,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
1385
1395
| AggregateKind :: CoroutineClosure ( def_id, _)
1386
1396
| AggregateKind :: Coroutine ( def_id, _) => {
1387
1397
let def_id = def_id. expect_local ( ) ;
1388
- let BorrowCheckResult { used_mut_upvars, .. } =
1389
- self . infcx . tcx . mir_borrowck ( def_id) ;
1398
+ let used_mut_upvars = self . root_cx . used_mut_upvars ( def_id) ;
1390
1399
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] ) ;
1400
+ // FIXME: We're cloning the `SmallVec` here to avoid borrowing `root_cx`
1401
+ // when calling `propagate_closure_used_mut_upvar`. This should ideally
1402
+ // be unnecessary.
1403
+ for field in used_mut_upvars. clone ( ) {
1404
+ self . propagate_closure_used_mut_upvar ( & operands[ field] ) ;
1393
1405
}
1394
1406
}
1395
1407
AggregateKind :: Adt ( ..)
0 commit comments