about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-07-31 23:21:24 +0000
committerbors <bors@rust-lang.org>2017-07-31 23:21:24 +0000
commitebf74d99b0bc25b5a4e35b0a2865580224ed0ef8 (patch)
tree700b950f7a7619f60aa3cf49dc514a2c53d09335 /src
parent37c7d0ebb3ec5b62bd37df9ee8826194e3c6300a (diff)
parent83eb264273fe7ace01b2100c116daa36f06920b8 (diff)
downloadrust-ebf74d99b0bc25b5a4e35b0a2865580224ed0ef8.tar.gz
rust-ebf74d99b0bc25b5a4e35b0a2865580224ed0ef8.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs53
-rw-r--r--src/librustc_borrowck/borrowck/move_data.rs9
2 files changed, 46 insertions, 16 deletions
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index 0124a77349c..76c4ac57a14 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -112,19 +112,28 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) {
     // is not yet stolen.
     tcx.mir_validated(owner_def_id).borrow();
 
-    let cfg = cfg::CFG::new(bccx.tcx, &body);
-    let AnalysisData { all_loans,
-                       loans: loan_dfcx,
-                       move_data: flowed_moves } =
-        build_borrowck_dataflow_data(bccx, &cfg, body_id);
-
-    check_loans::check_loans(bccx, &loan_dfcx, &flowed_moves, &all_loans, body);
+    // option dance because you can't capture an uninitialized variable
+    // by mut-ref.
+    let mut cfg = None;
+    if let Some(AnalysisData { all_loans,
+                               loans: loan_dfcx,
+                               move_data: flowed_moves }) =
+        build_borrowck_dataflow_data(bccx, false, body_id,
+                                     |bccx| {
+                                         cfg = Some(cfg::CFG::new(bccx.tcx, &body));
+                                         cfg.as_mut().unwrap()
+                                     })
+    {
+        check_loans::check_loans(bccx, &loan_dfcx, &flowed_moves, &all_loans, body);
+    }
 }
 
-fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
-                                          cfg: &cfg::CFG,
-                                          body_id: hir::BodyId)
-                                          -> AnalysisData<'a, 'tcx>
+fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tcx>,
+                                                 force_analysis: bool,
+                                                 body_id: hir::BodyId,
+                                                 get_cfg: F)
+                                                 -> Option<AnalysisData<'a, 'tcx>>
+    where F: FnOnce(&mut BorrowckCtxt<'a, 'tcx>) -> &'c cfg::CFG
 {
     // Check the body of fn items.
     let tcx = this.tcx;
@@ -137,6 +146,18 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
     let (all_loans, move_data) =
         gather_loans::gather_loans_in_fn(this, body_id);
 
+    if !force_analysis && move_data.is_empty() && all_loans.is_empty() {
+        // large arrays of data inserted as constants can take a lot of
+        // time and memory to borrow-check - see issue #36799. However,
+        // they don't have lvalues, so no borrow-check is actually needed.
+        // Recognize that case and skip borrow-checking.
+        debug!("skipping loan propagation for {:?} because of no loans", body_id);
+        return None;
+    } else {
+        debug!("propagating loans in {:?}", body_id);
+    }
+
+    let cfg = get_cfg(this);
     let mut loan_dfcx =
         DataFlowContext::new(this.tcx,
                              "borrowck",
@@ -159,9 +180,9 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
                                                       id_range,
                                                       body);
 
-    AnalysisData { all_loans: all_loans,
-                   loans: loan_dfcx,
-                   move_data:flowed_moves }
+    Some(AnalysisData { all_loans: all_loans,
+                        loans: loan_dfcx,
+                        move_data:flowed_moves })
 }
 
 /// Accessor for introspective clients inspecting `AnalysisData` and
@@ -178,8 +199,8 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>(
     let region_maps = tcx.region_maps(owner_def_id);
     let mut bccx = BorrowckCtxt { tcx, tables, region_maps, owner_def_id };
 
-    let dataflow_data = build_borrowck_dataflow_data(&mut bccx, cfg, body_id);
-    (bccx, dataflow_data)
+    let dataflow_data = build_borrowck_dataflow_data(&mut bccx, true, body_id, |_| cfg);
+    (bccx, dataflow_data.unwrap())
 }
 
 // ----------------------------------------------------------------------
diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs
index 0a31905c792..fd80e8320d6 100644
--- a/src/librustc_borrowck/borrowck/move_data.rs
+++ b/src/librustc_borrowck/borrowck/move_data.rs
@@ -220,6 +220,15 @@ impl<'a, 'tcx> MoveData<'tcx> {
         }
     }
 
+    /// return true if there are no trackable assignments or moves
+    /// in this move data - that means that there is nothing that
+    /// could cause a borrow error.
+    pub fn is_empty(&self) -> bool {
+        self.moves.borrow().is_empty() &&
+            self.path_assignments.borrow().is_empty() &&
+            self.var_assignments.borrow().is_empty()
+    }
+
     pub fn path_loan_path(&self, index: MovePathIndex) -> Rc<LoanPath<'tcx>> {
         (*self.paths.borrow())[index.get()].loan_path.clone()
     }