@@ -9,15 +9,15 @@ use rustc_target::spec::abi::Abi;
9
9
use syntax:: symbol:: sym;
10
10
use syntax_pos:: Span ;
11
11
12
- use std:: cell:: RefCell ;
13
12
use std:: fmt;
14
13
use std:: ops:: Deref ;
15
14
16
- use crate :: dataflow as old_dataflow;
17
- use super :: { ConstKind , Item , Qualif , is_lang_panic_fn} ;
18
- use super :: resolver:: { FlowSensitiveResolver , IndirectlyMutableResults , QualifResolver } ;
19
- use super :: qualifs:: { HasMutInterior , NeedsDrop } ;
15
+ use crate :: dataflow:: { self as old_dataflow, generic as dataflow} ;
16
+ use self :: old_dataflow:: IndirectlyMutableLocals ;
20
17
use super :: ops:: { self , NonConstOp } ;
18
+ use super :: qualifs:: { HasMutInterior , NeedsDrop } ;
19
+ use super :: resolver:: FlowSensitiveAnalysis ;
20
+ use super :: { ConstKind , Item , Qualif , is_lang_panic_fn} ;
21
21
22
22
#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
23
23
pub enum CheckOpResult {
@@ -26,9 +26,75 @@ pub enum CheckOpResult {
26
26
Allowed ,
27
27
}
28
28
29
+ pub type IndirectlyMutableResults < ' mir , ' tcx > =
30
+ old_dataflow:: DataflowResultsCursor < ' mir , ' tcx , IndirectlyMutableLocals < ' mir , ' tcx > > ;
31
+
32
+ struct QualifCursor < ' a , ' mir , ' tcx , Q : Qualif > {
33
+ cursor : dataflow:: ResultsCursor < ' mir , ' tcx , FlowSensitiveAnalysis < ' a , ' mir , ' tcx , Q > > ,
34
+ in_any_value_of_ty : BitSet < Local > ,
35
+ }
36
+
37
+ impl < Q : Qualif > QualifCursor < ' a , ' mir , ' tcx , Q > {
38
+ pub fn new (
39
+ q : Q ,
40
+ item : & ' a Item < ' mir , ' tcx > ,
41
+ dead_unwinds : & BitSet < BasicBlock > ,
42
+ ) -> Self {
43
+ let analysis = FlowSensitiveAnalysis :: new ( q, item) ;
44
+ let results =
45
+ dataflow:: Engine :: new ( item. tcx , item. body , item. def_id , dead_unwinds, analysis)
46
+ . iterate_to_fixpoint ( ) ;
47
+ let cursor = dataflow:: ResultsCursor :: new ( item. body , results) ;
48
+
49
+ let mut in_any_value_of_ty = BitSet :: new_empty ( item. body . local_decls . len ( ) ) ;
50
+ for ( local, decl) in item. body . local_decls . iter_enumerated ( ) {
51
+ if Q :: in_any_value_of_ty ( item, decl. ty ) {
52
+ in_any_value_of_ty. insert ( local) ;
53
+ }
54
+ }
55
+
56
+ QualifCursor {
57
+ cursor,
58
+ in_any_value_of_ty,
59
+ }
60
+ }
61
+ }
62
+
29
63
pub struct Qualifs < ' a , ' mir , ' tcx > {
30
- has_mut_interior : FlowSensitiveResolver < ' a , ' mir , ' tcx , HasMutInterior > ,
31
- needs_drop : FlowSensitiveResolver < ' a , ' mir , ' tcx , NeedsDrop > ,
64
+ has_mut_interior : QualifCursor < ' a , ' mir , ' tcx , HasMutInterior > ,
65
+ needs_drop : QualifCursor < ' a , ' mir , ' tcx , NeedsDrop > ,
66
+ indirectly_mutable : IndirectlyMutableResults < ' mir , ' tcx > ,
67
+ }
68
+
69
+ impl Qualifs < ' a , ' mir , ' tcx > {
70
+ fn indirectly_mutable ( & mut self , local : Local , location : Location ) -> bool {
71
+ self . indirectly_mutable . seek ( location) ;
72
+ self . indirectly_mutable . get ( ) . contains ( local)
73
+ }
74
+
75
+ /// Returns `true` if `local` is `NeedsDrop` at the given `Location`.
76
+ ///
77
+ /// Only updates the cursor if absolutely necessary
78
+ fn needs_drop_lazy_seek ( & mut self , local : Local , location : Location ) -> bool {
79
+ if !self . needs_drop . in_any_value_of_ty . contains ( local) {
80
+ return false ;
81
+ }
82
+
83
+ self . needs_drop . cursor . seek_before ( location) ;
84
+ self . needs_drop . cursor . get ( ) . contains ( local)
85
+ || self . indirectly_mutable ( local, location)
86
+ }
87
+
88
+ /// Returns `true` if `local` is `HasMutInterior`, but requires the `has_mut_interior` and
89
+ /// `indirectly_mutable` cursors to be updated beforehand.
90
+ fn has_mut_interior_eager_seek ( & self , local : Local ) -> bool {
91
+ if !self . has_mut_interior . in_any_value_of_ty . contains ( local) {
92
+ return false ;
93
+ }
94
+
95
+ self . has_mut_interior . cursor . get ( ) . contains ( local)
96
+ || self . indirectly_mutable . get ( ) . contains ( local)
97
+ }
32
98
}
33
99
34
100
pub struct Validator < ' a , ' mir , ' tcx > {
@@ -63,53 +129,43 @@ impl Deref for Validator<'_, 'mir, 'tcx> {
63
129
}
64
130
}
65
131
66
- pub fn compute_indirectly_mutable_locals < ' mir , ' tcx > (
67
- item : & Item < ' mir , ' tcx > ,
68
- ) -> RefCell < IndirectlyMutableResults < ' mir , ' tcx > > {
69
- let dead_unwinds = BitSet :: new_empty ( item. body . basic_blocks ( ) . len ( ) ) ;
70
-
71
- let indirectly_mutable_locals = old_dataflow:: do_dataflow (
72
- item. tcx ,
73
- item. body ,
74
- item. def_id ,
75
- & item. tcx . get_attrs ( item. def_id ) ,
76
- & dead_unwinds,
77
- old_dataflow:: IndirectlyMutableLocals :: new ( item. tcx , item. body , item. param_env ) ,
78
- |_, local| old_dataflow:: DebugFormatted :: new ( & local) ,
79
- ) ;
80
-
81
- let indirectly_mutable_locals = old_dataflow:: DataflowResultsCursor :: new (
82
- indirectly_mutable_locals,
83
- item. body ,
84
- ) ;
85
-
86
- RefCell :: new ( indirectly_mutable_locals)
87
- }
88
-
89
132
impl Validator < ' a , ' mir , ' tcx > {
90
133
pub fn new (
91
134
item : & ' a Item < ' mir , ' tcx > ,
92
- indirectly_mutable_locals : & ' a RefCell < IndirectlyMutableResults < ' mir , ' tcx > > ,
93
135
) -> Self {
94
136
let dead_unwinds = BitSet :: new_empty ( item. body . basic_blocks ( ) . len ( ) ) ;
95
137
96
- let needs_drop = FlowSensitiveResolver :: new (
138
+ let needs_drop = QualifCursor :: new (
97
139
NeedsDrop ,
98
140
item,
99
- indirectly_mutable_locals,
100
141
& dead_unwinds,
101
142
) ;
102
143
103
- let has_mut_interior = FlowSensitiveResolver :: new (
144
+ let has_mut_interior = QualifCursor :: new (
104
145
HasMutInterior ,
105
146
item,
106
- indirectly_mutable_locals,
107
147
& dead_unwinds,
108
148
) ;
109
149
150
+ let indirectly_mutable = old_dataflow:: do_dataflow (
151
+ item. tcx ,
152
+ item. body ,
153
+ item. def_id ,
154
+ & item. tcx . get_attrs ( item. def_id ) ,
155
+ & dead_unwinds,
156
+ old_dataflow:: IndirectlyMutableLocals :: new ( item. tcx , item. body , item. param_env ) ,
157
+ |_, local| old_dataflow:: DebugFormatted :: new ( & local) ,
158
+ ) ;
159
+
160
+ let indirectly_mutable = old_dataflow:: DataflowResultsCursor :: new (
161
+ indirectly_mutable,
162
+ item. body ,
163
+ ) ;
164
+
110
165
let qualifs = Qualifs {
111
166
needs_drop,
112
167
has_mut_interior,
168
+ indirectly_mutable,
113
169
} ;
114
170
115
171
Validator {
@@ -122,14 +178,6 @@ impl Validator<'a, 'mir, 'tcx> {
122
178
}
123
179
}
124
180
125
- /// Resets the `QualifResolver`s used by this `Validator` and returns them so they can be
126
- /// reused.
127
- pub fn into_qualifs ( mut self ) -> Qualifs < ' a , ' mir , ' tcx > {
128
- self . qualifs . needs_drop . reset ( ) ;
129
- self . qualifs . has_mut_interior . reset ( ) ;
130
- self . qualifs
131
- }
132
-
133
181
pub fn take_errors ( & mut self ) -> Vec < ( Span , String ) > {
134
182
std:: mem:: replace ( & mut self . errors , vec ! [ ] )
135
183
}
@@ -304,10 +352,16 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
304
352
// it depends on `HasMutInterior` being set for mutable borrows as well as values with
305
353
// interior mutability.
306
354
if let Rvalue :: Ref ( _, kind, ref borrowed_place) = * rvalue {
307
- let rvalue_has_mut_interior = {
308
- let has_mut_interior = self . qualifs . has_mut_interior . get ( ) ;
309
- HasMutInterior :: in_rvalue ( & self . item , & |l| has_mut_interior. contains ( l) , rvalue)
310
- } ;
355
+ // FIXME: Change the `in_*` methods to take a `FnMut` so we don't have to manually seek
356
+ // the cursors beforehand.
357
+ self . qualifs . has_mut_interior . cursor . seek_before ( location) ;
358
+ self . qualifs . indirectly_mutable . seek ( location) ;
359
+
360
+ let rvalue_has_mut_interior = HasMutInterior :: in_rvalue (
361
+ & self . item ,
362
+ & |local| self . qualifs . has_mut_interior_eager_seek ( local) ,
363
+ rvalue,
364
+ ) ;
311
365
312
366
if rvalue_has_mut_interior {
313
367
let is_derived_from_illegal_borrow = match borrowed_place. as_local ( ) {
@@ -402,9 +456,6 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
402
456
fn visit_statement ( & mut self , statement : & Statement < ' tcx > , location : Location ) {
403
457
trace ! ( "visit_statement: statement={:?} location={:?}" , statement, location) ;
404
458
405
- self . qualifs . needs_drop . visit_statement ( statement, location) ;
406
- self . qualifs . has_mut_interior . visit_statement ( statement, location) ;
407
-
408
459
match statement. kind {
409
460
StatementKind :: Assign ( ..) => {
410
461
self . super_statement ( statement, location) ;
@@ -424,15 +475,6 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
424
475
}
425
476
}
426
477
427
- fn visit_terminator ( & mut self , terminator : & Terminator < ' tcx > , location : Location ) {
428
- trace ! ( "visit_terminator: terminator={:?} location={:?}" , terminator, location) ;
429
-
430
- self . qualifs . needs_drop . visit_terminator ( terminator, location) ;
431
- self . qualifs . has_mut_interior . visit_terminator ( terminator, location) ;
432
-
433
- self . super_terminator ( terminator, location) ;
434
- }
435
-
436
478
fn visit_terminator_kind ( & mut self , kind : & TerminatorKind < ' tcx > , location : Location ) {
437
479
trace ! ( "visit_terminator_kind: kind={:?} location={:?}" , kind, location) ;
438
480
self . super_terminator_kind ( kind, location) ;
@@ -511,7 +553,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
511
553
let needs_drop = if let Some ( local) = dropped_place. as_local ( ) {
512
554
// Use the span where the local was declared as the span of the drop error.
513
555
err_span = self . body . local_decls [ local] . source_info . span ;
514
- self . qualifs . needs_drop . contains ( local)
556
+ self . qualifs . needs_drop_lazy_seek ( local, location )
515
557
} else {
516
558
true
517
559
} ;
0 commit comments