@@ -15,13 +15,13 @@ use rustc;
1515use rustc:: hir;
1616use rustc:: hir:: def_id:: DefId ;
1717use rustc:: middle:: region;
18- use rustc:: mir:: { self , Location , Place , Mir , TerminatorKind } ;
18+ use rustc:: mir:: { self , Location , Place , Mir } ;
1919use rustc:: ty:: TyCtxt ;
2020use rustc:: ty:: { RegionKind , RegionVid } ;
2121use rustc:: ty:: RegionKind :: ReScope ;
2222
2323use rustc_data_structures:: bitslice:: BitwiseOperator ;
24- use rustc_data_structures:: fx:: FxHashMap ;
24+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
2525use rustc_data_structures:: indexed_set:: IdxSet ;
2626use rustc_data_structures:: indexed_vec:: IndexVec ;
2727use rustc_data_structures:: sync:: Lrc ;
@@ -60,104 +60,33 @@ fn precompute_borrows_out_of_scope<'a, 'tcx>(
6060 borrow_index : BorrowIndex ,
6161 borrow_region : RegionVid ,
6262 location : Location ,
63- visited_locations : & mut Vec < Location >
6463) {
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+ }
7879
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 ] ;
8382 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+ }
16190 }
16291}
16392
@@ -182,8 +111,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
182111
183112 precompute_borrows_out_of_scope ( mir, & nonlexical_regioncx,
184113 & mut borrows_out_of_scope_at_location,
185- borrow_index, borrow_region, location,
186- & mut Vec :: new ( ) ) ;
114+ borrow_index, borrow_region, location) ;
187115 }
188116
189117 Borrows {
0 commit comments