Skip to content

Commit ebf74d9

Browse files
committed
Auto merge of #43547 - arielb1:no-borrow-no-check, r=nikomatsakis
borrowck: skip CFG construction when there is nothing to propagate CFG construction takes a large amount of time and memory, especially for large constants. If such a constant contains no actions on lvalues, it can't have borrowck problems and can be ignored by it. This removes the 4.9GB borrowck peak from #36799. It seems that HIR had grown by 300MB and MIR had grown by 500MB from the last massif collection and that remains to be investigated, but this at least shaves the borrowck peak. r? @nikomatsakis
2 parents 37c7d0e + 83eb264 commit ebf74d9

File tree

2 files changed

+46
-16
lines changed

2 files changed

+46
-16
lines changed

src/librustc_borrowck/borrowck/mod.rs

+37-16
Original file line numberDiff line numberDiff line change
@@ -112,19 +112,28 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) {
112112
// is not yet stolen.
113113
tcx.mir_validated(owner_def_id).borrow();
114114

115-
let cfg = cfg::CFG::new(bccx.tcx, &body);
116-
let AnalysisData { all_loans,
117-
loans: loan_dfcx,
118-
move_data: flowed_moves } =
119-
build_borrowck_dataflow_data(bccx, &cfg, body_id);
120-
121-
check_loans::check_loans(bccx, &loan_dfcx, &flowed_moves, &all_loans, body);
115+
// option dance because you can't capture an uninitialized variable
116+
// by mut-ref.
117+
let mut cfg = None;
118+
if let Some(AnalysisData { all_loans,
119+
loans: loan_dfcx,
120+
move_data: flowed_moves }) =
121+
build_borrowck_dataflow_data(bccx, false, body_id,
122+
|bccx| {
123+
cfg = Some(cfg::CFG::new(bccx.tcx, &body));
124+
cfg.as_mut().unwrap()
125+
})
126+
{
127+
check_loans::check_loans(bccx, &loan_dfcx, &flowed_moves, &all_loans, body);
128+
}
122129
}
123130

124-
fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
125-
cfg: &cfg::CFG,
126-
body_id: hir::BodyId)
127-
-> AnalysisData<'a, 'tcx>
131+
fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tcx>,
132+
force_analysis: bool,
133+
body_id: hir::BodyId,
134+
get_cfg: F)
135+
-> Option<AnalysisData<'a, 'tcx>>
136+
where F: FnOnce(&mut BorrowckCtxt<'a, 'tcx>) -> &'c cfg::CFG
128137
{
129138
// Check the body of fn items.
130139
let tcx = this.tcx;
@@ -137,6 +146,18 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
137146
let (all_loans, move_data) =
138147
gather_loans::gather_loans_in_fn(this, body_id);
139148

149+
if !force_analysis && move_data.is_empty() && all_loans.is_empty() {
150+
// large arrays of data inserted as constants can take a lot of
151+
// time and memory to borrow-check - see issue #36799. However,
152+
// they don't have lvalues, so no borrow-check is actually needed.
153+
// Recognize that case and skip borrow-checking.
154+
debug!("skipping loan propagation for {:?} because of no loans", body_id);
155+
return None;
156+
} else {
157+
debug!("propagating loans in {:?}", body_id);
158+
}
159+
160+
let cfg = get_cfg(this);
140161
let mut loan_dfcx =
141162
DataFlowContext::new(this.tcx,
142163
"borrowck",
@@ -159,9 +180,9 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
159180
id_range,
160181
body);
161182

162-
AnalysisData { all_loans: all_loans,
163-
loans: loan_dfcx,
164-
move_data:flowed_moves }
183+
Some(AnalysisData { all_loans: all_loans,
184+
loans: loan_dfcx,
185+
move_data:flowed_moves })
165186
}
166187

167188
/// Accessor for introspective clients inspecting `AnalysisData` and
@@ -178,8 +199,8 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>(
178199
let region_maps = tcx.region_maps(owner_def_id);
179200
let mut bccx = BorrowckCtxt { tcx, tables, region_maps, owner_def_id };
180201

181-
let dataflow_data = build_borrowck_dataflow_data(&mut bccx, cfg, body_id);
182-
(bccx, dataflow_data)
202+
let dataflow_data = build_borrowck_dataflow_data(&mut bccx, true, body_id, |_| cfg);
203+
(bccx, dataflow_data.unwrap())
183204
}
184205

185206
// ----------------------------------------------------------------------

src/librustc_borrowck/borrowck/move_data.rs

+9
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,15 @@ impl<'a, 'tcx> MoveData<'tcx> {
220220
}
221221
}
222222

223+
/// return true if there are no trackable assignments or moves
224+
/// in this move data - that means that there is nothing that
225+
/// could cause a borrow error.
226+
pub fn is_empty(&self) -> bool {
227+
self.moves.borrow().is_empty() &&
228+
self.path_assignments.borrow().is_empty() &&
229+
self.var_assignments.borrow().is_empty()
230+
}
231+
223232
pub fn path_loan_path(&self, index: MovePathIndex) -> Rc<LoanPath<'tcx>> {
224233
(*self.paths.borrow())[index.get()].loan_path.clone()
225234
}

0 commit comments

Comments
 (0)