Skip to content

Commit 4500fe0

Browse files
committed
Refactored DFS to be much cleaner. Added continue after noting that borrow is out of scope at location.
1 parent 24ee506 commit 4500fe0

File tree

1 file changed

+27
-99
lines changed

1 file changed

+27
-99
lines changed

src/librustc_mir/dataflow/impls/borrows.rs

Lines changed: 27 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ use rustc;
1515
use rustc::hir;
1616
use rustc::hir::def_id::DefId;
1717
use rustc::middle::region;
18-
use rustc::mir::{self, Location, Place, Mir, TerminatorKind};
18+
use rustc::mir::{self, Location, Place, Mir};
1919
use rustc::ty::TyCtxt;
2020
use rustc::ty::{RegionKind, RegionVid};
2121
use rustc::ty::RegionKind::ReScope;
2222

2323
use rustc_data_structures::bitslice::BitwiseOperator;
24-
use rustc_data_structures::fx::FxHashMap;
24+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
2525
use rustc_data_structures::indexed_set::IdxSet;
2626
use rustc_data_structures::indexed_vec::IndexVec;
2727
use 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

Comments
 (0)