@@ -15,13 +15,13 @@ use rustc;
15
15
use rustc:: hir;
16
16
use rustc:: hir:: def_id:: DefId ;
17
17
use rustc:: middle:: region;
18
- use rustc:: mir:: { self , Location , Place , Mir , TerminatorKind } ;
18
+ use rustc:: mir:: { self , Location , Place , Mir } ;
19
19
use rustc:: ty:: TyCtxt ;
20
20
use rustc:: ty:: { RegionKind , RegionVid } ;
21
21
use rustc:: ty:: RegionKind :: ReScope ;
22
22
23
23
use rustc_data_structures:: bitslice:: BitwiseOperator ;
24
- use rustc_data_structures:: fx:: FxHashMap ;
24
+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
25
25
use rustc_data_structures:: indexed_set:: IdxSet ;
26
26
use rustc_data_structures:: indexed_vec:: IndexVec ;
27
27
use rustc_data_structures:: sync:: Lrc ;
@@ -60,104 +60,33 @@ fn precompute_borrows_out_of_scope<'a, 'tcx>(
60
60
borrow_index : BorrowIndex ,
61
61
borrow_region : RegionVid ,
62
62
location : Location ,
63
- visited_locations : & mut Vec < Location >
64
63
) {
65
- // Check if we have already visited this location and skip
66
- // it if we have - avoids infinite loops.
67
- if visited_locations. contains ( & location) { return ; }
68
- visited_locations. push ( location. clone ( ) ) ;
69
-
70
- // Next, add the borrow index to the current location's vector if the region does
71
- // not contain the point at that location (or create a new vector if required).
72
- if !regioncx. region_contains_point ( borrow_region, location) {
73
- borrows_out_of_scope_at_location
74
- . entry ( location. clone ( ) )
75
- . and_modify ( |m| m. push ( borrow_index) )
76
- . or_insert ( vec ! [ borrow_index ] ) ;
77
- }
64
+ // Keep track of places we've locations to check and locations that we have checked.
65
+ let mut stack = vec ! [ location ] ;
66
+ let mut visited = FxHashSet ( ) ;
67
+ visited. insert ( location) ;
68
+
69
+ while let Some ( location) = stack. pop ( ) {
70
+ // If region does not contain a point at the location, then add to list and skip
71
+ // successor locations.
72
+ if !regioncx. region_contains_point ( borrow_region, location) {
73
+ borrows_out_of_scope_at_location
74
+ . entry ( location)
75
+ . or_insert ( vec ! [ ] )
76
+ . push ( borrow_index) ;
77
+ continue ;
78
+ }
78
79
79
- let bb_data = & mir[ location. block ] ;
80
- // If we are past the last statement, then check the terminator
81
- // to determine which location to proceed to.
82
- if location. statement_index == bb_data. statements . len ( ) {
80
+ // Add successors to locations to visit, if not visited before.
81
+ let bb_data = & mir[ location. block ] ;
83
82
if let Some ( ref terminator) = bb_data. terminator {
84
- match terminator. kind {
85
- TerminatorKind :: Goto { target } |
86
- TerminatorKind :: FalseEdges { real_target : target, .. } |
87
- TerminatorKind :: FalseUnwind { real_target : target, .. } => {
88
- precompute_borrows_out_of_scope (
89
- mir, regioncx, borrows_out_of_scope_at_location,
90
- borrow_index, borrow_region, target. start_location ( ) ,
91
- visited_locations
92
- ) ;
93
- } ,
94
- TerminatorKind :: SwitchInt { ref targets, .. } => {
95
- for block in targets {
96
- precompute_borrows_out_of_scope (
97
- mir, regioncx, borrows_out_of_scope_at_location,
98
- borrow_index, borrow_region, block. start_location ( ) ,
99
- visited_locations
100
- ) ;
101
- }
102
- } ,
103
- TerminatorKind :: Drop { target, unwind, .. } |
104
- TerminatorKind :: DropAndReplace { target, unwind, .. } => {
105
- precompute_borrows_out_of_scope (
106
- mir, regioncx, borrows_out_of_scope_at_location,
107
- borrow_index, borrow_region, target. start_location ( ) ,
108
- visited_locations
109
- ) ;
110
-
111
- if let Some ( unwind_block) = unwind {
112
- precompute_borrows_out_of_scope (
113
- mir, regioncx, borrows_out_of_scope_at_location,
114
- borrow_index, borrow_region, unwind_block. start_location ( ) ,
115
- visited_locations
116
- ) ;
117
- }
118
- } ,
119
- TerminatorKind :: Call { ref destination, cleanup, .. } => {
120
- if let Some ( ( _, block) ) = destination {
121
- precompute_borrows_out_of_scope (
122
- mir, regioncx, borrows_out_of_scope_at_location,
123
- borrow_index, borrow_region, block. start_location ( ) ,
124
- visited_locations
125
- ) ;
126
- }
127
-
128
- if let Some ( block) = cleanup {
129
- precompute_borrows_out_of_scope (
130
- mir, regioncx, borrows_out_of_scope_at_location,
131
- borrow_index, borrow_region, block. start_location ( ) ,
132
- visited_locations
133
- ) ;
134
- }
135
- } ,
136
- TerminatorKind :: Assert { target, cleanup, .. } |
137
- TerminatorKind :: Yield { resume : target, drop : cleanup, .. } => {
138
- precompute_borrows_out_of_scope (
139
- mir, regioncx, borrows_out_of_scope_at_location,
140
- borrow_index, borrow_region, target. start_location ( ) ,
141
- visited_locations
142
- ) ;
143
-
144
- if let Some ( block) = cleanup {
145
- precompute_borrows_out_of_scope (
146
- mir, regioncx, borrows_out_of_scope_at_location,
147
- borrow_index, borrow_region, block. start_location ( ) ,
148
- visited_locations
149
- ) ;
150
- }
151
- } ,
152
- _ => { } ,
153
- } ;
154
- } ;
155
- // If we're not on the last statement, then go to the next
156
- // statement in this block.
157
- } else {
158
- precompute_borrows_out_of_scope ( mir, regioncx, borrows_out_of_scope_at_location,
159
- borrow_index, borrow_region,
160
- location. successor_within_block ( ) , visited_locations) ;
83
+ for block in terminator. successors ( ) {
84
+ let loc = block. start_location ( ) ;
85
+ if visited. insert ( loc) {
86
+ stack. push ( loc) ;
87
+ }
88
+ }
89
+ }
161
90
}
162
91
}
163
92
@@ -182,8 +111,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
182
111
183
112
precompute_borrows_out_of_scope ( mir, & nonlexical_regioncx,
184
113
& mut borrows_out_of_scope_at_location,
185
- borrow_index, borrow_region, location,
186
- & mut Vec :: new ( ) ) ;
114
+ borrow_index, borrow_region, location) ;
187
115
}
188
116
189
117
Borrows {
0 commit comments