@@ -17,64 +17,70 @@ use borrow_check::{Context, ContextKind};
17
17
use borrow_check:: { LocalMutationIsAllowed , MutateMode } ;
18
18
use borrow_check:: ArtificialField ;
19
19
use borrow_check:: { ReadKind , WriteKind , Overlap } ;
20
- use borrow_check:: nll:: region_infer:: RegionInferenceContext ;
21
20
use borrow_check:: nll:: facts:: AllFacts ;
22
21
use dataflow:: move_paths:: indexes:: BorrowIndex ;
23
22
use rustc:: hir;
23
+ use rustc:: hir:: def_id:: DefId ;
24
24
use rustc:: infer:: InferCtxt ;
25
25
use rustc:: mir:: visit:: Visitor ;
26
26
use rustc:: mir:: { BasicBlock , Location , Mir , Place , Rvalue , Projection } ;
27
27
use rustc:: mir:: { Local , ProjectionElem } ;
28
28
use rustc:: mir:: { Statement , StatementKind } ;
29
29
use rustc:: mir:: { Terminator , TerminatorKind } ;
30
30
use rustc:: mir:: { Field , Operand , BorrowKind } ;
31
- use rustc:: ty;
31
+ use rustc:: ty:: { self , ParamEnv } ;
32
32
use rustc_data_structures:: indexed_vec:: Idx ;
33
33
use std:: iter;
34
34
35
35
pub ( super ) fn generate_invalidates < ' cx , ' gcx , ' tcx > (
36
36
infcx : & InferCtxt < ' cx , ' gcx , ' tcx > ,
37
- regioncx : & mut RegionInferenceContext < ' tcx > ,
38
37
all_facts : & mut Option < AllFacts > ,
39
38
location_table : & LocationTable ,
40
39
mir : & Mir < ' tcx > ,
40
+ mir_def_id : DefId ,
41
41
borrow_set : & BorrowSet < ' tcx > ,
42
42
) {
43
43
if !all_facts. is_some ( ) {
44
44
// Nothing to do if we don't have any facts
45
45
return ;
46
46
}
47
47
48
- let mut ig = InvalidationGenerator {
49
- all_facts : & mut all_facts. unwrap ( ) ,
50
- borrow_set,
51
- infcx,
52
- regioncx,
53
- location_table,
54
- mir,
55
- } ;
48
+ let param_env = infcx. tcx . param_env ( mir_def_id) ;
49
+
50
+ let mut all_facts_taken = all_facts. take ( ) . unwrap ( ) ;
51
+ {
52
+ let mut ig = InvalidationGenerator {
53
+ all_facts : & mut all_facts_taken,
54
+ borrow_set,
55
+ infcx,
56
+ location_table,
57
+ mir,
58
+ param_env,
59
+ } ;
60
+ ig. visit_mir ( mir) ;
61
+ }
62
+ * all_facts = Some ( all_facts_taken) ;
56
63
}
57
64
58
65
/// 'cg = the duration of the constraint generation process itself.
59
- struct InvalidationGenerator < ' cg , ' cx : ' cg , ' gcx : ' tcx , ' tcx : ' cx > {
66
+ struct InvalidationGenerator < ' cg , ' cx : ' cg , ' tcx : ' cx , ' gcx : ' tcx > {
60
67
infcx : & ' cg InferCtxt < ' cx , ' gcx , ' tcx > ,
61
68
all_facts : & ' cg mut AllFacts ,
62
69
location_table : & ' cg LocationTable ,
63
- regioncx : & ' cg mut RegionInferenceContext < ' tcx > ,
64
70
mir : & ' cg Mir < ' tcx > ,
65
71
borrow_set : & ' cg BorrowSet < ' tcx > ,
72
+ param_env : ParamEnv < ' gcx > ,
66
73
}
67
74
68
75
/// Visits the whole MIR and generates invalidates() facts
69
76
/// Most of the code implementing this was stolen from borrow_check/mod.rs
70
- impl < ' cg , ' cx : ' cg , ' gcx : ' tcx , ' tcx : ' cx > Visitor < ' tcx > for InvalidationGenerator < ' cg , ' cx , ' gcx , ' tcx > {
77
+ impl < ' cg , ' cx , ' tcx , ' gcx > Visitor < ' tcx > for InvalidationGenerator < ' cg , ' cx , ' tcx , ' gcx > {
71
78
fn visit_statement ( & mut self , block : BasicBlock , statement : & Statement < ' tcx > , location : Location ) {
72
79
match statement. kind {
73
80
StatementKind :: Assign ( ref lhs, ref rhs) => {
74
81
self . consume_rvalue (
75
82
ContextKind :: AssignRhs . new ( location) ,
76
83
rhs,
77
- location
78
84
) ;
79
85
80
86
self . mutate_place (
@@ -170,6 +176,7 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> Visitor<'tcx> for InvalidationGenerat
170
176
let gcx = tcx. global_tcx ( ) ;
171
177
let drop_place_ty = drop_place. ty ( self . mir , tcx) ;
172
178
let drop_place_ty = tcx. erase_regions ( & drop_place_ty) . to_ty ( tcx) ;
179
+ let drop_place_ty = gcx. lift ( & drop_place_ty) . unwrap ( ) ;
173
180
self . visit_terminator_drop ( location, terminator, drop_place, drop_place_ty) ;
174
181
}
175
182
TerminatorKind :: DropAndReplace {
@@ -275,7 +282,7 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> Visitor<'tcx> for InvalidationGenerat
275
282
}
276
283
}
277
284
278
- impl < ' cg , ' cx : ' cg , ' gcx : ' tcx , ' tcx : ' cx > InvalidationGenerator < ' cg , ' cx , ' gcx , ' tcx > {
285
+ impl < ' cg , ' cx , ' tcx , ' gcx > InvalidationGenerator < ' cg , ' cx , ' tcx , ' gcx > {
279
286
/// Simulates dropping of a variable
280
287
fn visit_terminator_drop (
281
288
& mut self ,
@@ -286,10 +293,10 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> InvalidationGenerator<'cg, 'cx, 'gcx,
286
293
) {
287
294
let gcx = self . infcx . tcx . global_tcx ( ) ;
288
295
let drop_field = |
289
- ig : & mut InvalidationGenerator < ' cg , ' cx , ' gcx , ' tcx > ,
290
- ( index, field) : ( usize , ty:: Ty < ' gcx > ) ,
296
+ ig : & mut InvalidationGenerator < ' cg , ' cx , ' gcx , ' tcx > ,
297
+ ( index, field) : ( usize , ty:: Ty < ' gcx > ) ,
291
298
| {
292
- let field_ty = gcx. normalize_erasing_regions( self . mir . param_env, field) ;
299
+ let field_ty = gcx. normalize_erasing_regions( ig . param_env, field) ;
293
300
let place = drop_place. clone( ) . field( Field :: new( index) , field_ty) ;
294
301
295
302
ig. visit_terminator_drop( loc, term, & place, field_ty) ;
@@ -351,7 +358,7 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> InvalidationGenerator<'cg, 'cx, 'gcx,
351
358
context: Context ,
352
359
place: & Place < ' tcx > ,
353
360
kind: ShallowOrDeep ,
354
- mode : MutateMode ,
361
+ _mode : MutateMode ,
355
362
) {
356
363
self . access_place(
357
364
context,
@@ -393,7 +400,6 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> InvalidationGenerator<'cg, 'cx, 'gcx,
393
400
& mut self ,
394
401
context: Context ,
395
402
rvalue: & Rvalue < ' tcx > ,
396
- location: Location ,
397
403
) {
398
404
match * rvalue {
399
405
Rvalue : : Ref ( _ /*rgn*/ , bk, ref place) => {
@@ -447,7 +453,7 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> InvalidationGenerator<'cg, 'cx, 'gcx,
447
453
Rvalue :: NullaryOp ( _op, _ty) => {
448
454
}
449
455
450
- Rvalue :: Aggregate ( ref aggregate_kind , ref operands) => {
456
+ Rvalue :: Aggregate ( _ , ref operands) => {
451
457
for operand in operands {
452
458
self. consume_operand( context, operand) ;
453
459
}
@@ -461,7 +467,7 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> InvalidationGenerator<'cg, 'cx, 'gcx,
461
467
context: Context ,
462
468
place: & Place < ' tcx > ,
463
469
kind: ( ShallowOrDeep , ReadOrWrite ) ,
464
- is_local_mutation_allowed : LocalMutationIsAllowed ,
470
+ _is_local_mutation_allowed : LocalMutationIsAllowed ,
465
471
) {
466
472
let ( sd, rw) = kind;
467
473
// note: not doing check_access_permissions checks because they don't generate invalidates
@@ -502,7 +508,7 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> InvalidationGenerator<'cg, 'cx, 'gcx,
502
508
// Reads/reservations don't invalidate shared borrows
503
509
}
504
510
505
- ( Read ( kind ) , BorrowKind :: Unique ) | ( Read ( kind ) , BorrowKind :: Mut { .. } ) => {
511
+ ( Read ( _ ) , BorrowKind :: Unique ) | ( Read ( _ ) , BorrowKind :: Mut { .. } ) => {
506
512
// Reading from mere reservations of mutable-borrows is OK.
507
513
if !this. is_active( borrow, context. loc) {
508
514
// If the borrow isn't active yet, reads don't invalidate it
@@ -512,20 +518,13 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> InvalidationGenerator<'cg, 'cx, 'gcx,
512
518
513
519
// Unique and mutable borrows are invalidated by reads from any
514
520
// involved path
515
- match kind {
516
- ReadKind :: Copy => {
517
- this. generate_invalidates( borrow_index, context. loc) ;
518
- }
519
- ReadKind :: Borrow ( bk) => {
520
- this. generate_invalidates( borrow_index, context. loc) ;
521
- }
522
- }
521
+ this. generate_invalidates( borrow_index, context. loc) ;
523
522
}
524
523
525
- ( Reservation ( kind ) , BorrowKind :: Unique )
526
- | ( Reservation ( kind ) , BorrowKind :: Mut { .. } )
527
- | ( Activation ( kind , _) , _)
528
- | ( Write ( kind ) , _) => {
524
+ ( Reservation ( _ ) , BorrowKind :: Unique )
525
+ | ( Reservation ( _ ) , BorrowKind :: Mut { .. } )
526
+ | ( Activation ( _ , _) , _)
527
+ | ( Write ( _ ) , _) => {
529
528
// unique or mutable borrows are invalidated by writes.
530
529
// Reservations count as writes since we need to check
531
530
// that activating the borrow will be OK
@@ -588,6 +587,23 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> InvalidationGenerator<'cg, 'cx, 'gcx,
588
587
}
589
588
}
590
589
590
+ /// Determine if a given two-phase borrow is active using dominator information
591
+ fn is_active ( & self , borrow : & BorrowData , location : Location ) -> bool {
592
+ // If it's not two-phase, the borrow is definitely active
593
+ if !self . allow_two_phase_borrow ( borrow. kind ) {
594
+ return true ;
595
+ }
596
+ if borrow. activation_location . is_none ( ) {
597
+ return false ;
598
+ }
599
+ let activation_location = borrow. activation_location . unwrap ( ) ;
600
+ if activation_location. block == location. block {
601
+ activation_location. statement_index >= location. statement_index
602
+ } else {
603
+ self . mir . dominators ( ) . is_dominated_by ( location. block , activation_location. block )
604
+ }
605
+ }
606
+
591
607
/// Returns whether an access of kind `access` to `access_place` conflicts with
592
608
/// a borrow/full access to `borrow_place` (for deep accesses to mutable
593
609
/// locations, this function is symmetric between `borrow_place` & `access_place`).
0 commit comments