about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-05-29 15:02:39 +0000
committerbors <bors@rust-lang.org>2018-05-29 15:02:39 +0000
commit59c0f5913ddc2f66c1ff8ab612f7027e38c85a6d (patch)
tree41fac7fde766c9449fad1890004abc958884d49c
parent889d8dcaa7546acf5b2f406b338caa708a8d93f8 (diff)
parentc3d688962d2940a033f4b4df85b8ab8417981210 (diff)
downloadrust-59c0f5913ddc2f66c1ff8ab612f7027e38c85a6d.tar.gz
rust-59c0f5913ddc2f66c1ff8ab612f7027e38c85a6d.zip
Auto merge of #51133 - spastorino:make_borrowck_use_output, r=nikomatsakis
Make borrowck use polonius output
-rw-r--r--src/Cargo.lock19
-rw-r--r--src/librustc/Cargo.toml2
-rw-r--r--src/librustc/session/config.rs2
-rw-r--r--src/librustc_mir/Cargo.toml3
-rw-r--r--src/librustc_mir/borrow_check/flows.rs39
-rw-r--r--src/librustc_mir/borrow_check/mod.rs7
-rw-r--r--src/librustc_mir/borrow_check/nll/mod.rs139
-rw-r--r--src/librustc_mir/lib.rs1
-rw-r--r--src/tools/tidy/src/deps.rs1
9 files changed, 139 insertions, 74 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index 7dce201505a..d61f007b6a5 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -558,6 +558,11 @@ dependencies = [
 ]
 
 [[package]]
+name = "datafrog"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "debug_unreachable"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1450,8 +1455,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "polonius-engine"
-version = "0.1.1"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "precomputed-hash"
@@ -1775,7 +1784,7 @@ dependencies = [
  "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "polonius-engine 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "polonius-engine 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
  "rustc_apfloat 0.0.0",
  "rustc_data_structures 0.0.0",
@@ -2159,10 +2168,11 @@ dependencies = [
  "arena 0.0.0",
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "graphviz 0.0.0",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "polonius-engine 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "polonius-engine 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_apfloat 0.0.0",
  "rustc_data_structures 0.0.0",
@@ -3069,6 +3079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4"
 "checksum curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "aaf20bbe084f285f215eef2165feed70d6b75ba29cad24469badb853a4a287d0"
 "checksum curl-sys 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71c63a540a9ee4e15e56c3ed9b11a2f121239b9f6d7b7fe30f616e048148df9a"
+"checksum datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16d724bf4ffe77cdceeecd461009b5f8d9e23c5d645d68bedb4586bf43e7e142"
 "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
 "checksum derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ceed73957c449214f8440eec8ad7fa282b67dc9eacbb24a3085b15d60397a17a"
 "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
@@ -3162,7 +3173,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03"
 "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2"
 "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
-"checksum polonius-engine 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6201ffe79e3da53bd065fbec2a9b391e5a0dc21038b39bb300612ddc658eb7ee"
+"checksum polonius-engine 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9385a6d8f8ff6fd7e48a803c6a77fb89cc929dc7e2af6bf972494bbc8ff8b9e4"
 "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6"
 "checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118"
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index 83cf4469f4d..df68bf1fd9a 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -16,7 +16,7 @@ graphviz = { path = "../libgraphviz" }
 jobserver = "0.1"
 lazy_static = "1.0.0"
 log = { version = "0.4", features = ["release_max_level_info", "std"] }
-polonius-engine = "0.1.1"
+polonius-engine = "0.4.0"
 proc_macro = { path = "../libproc_macro" }
 rustc_apfloat = { path = "../librustc_apfloat" }
 rustc_target = { path = "../librustc_target" }
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index b3f1b9c8e62..755b4af1a3a 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -1296,6 +1296,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
                        "dump facts from NLL analysis into side files"),
     disable_nll_user_type_assert: bool = (false, parse_bool, [UNTRACKED],
         "disable user provided type assertion in NLL"),
+    polonius: bool = (false, parse_bool, [UNTRACKED],
+        "enable polonius-based borrow-checker"),
     codegen_time_graph: bool = (false, parse_bool, [UNTRACKED],
         "generate a graphical HTML report of time spent in codegen and LLVM"),
     thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index e88ff38ed7d..512ab53f401 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -11,10 +11,11 @@ crate-type = ["dylib"]
 [dependencies]
 arena = { path = "../libarena" }
 bitflags = "1.0"
+either = "1.5.0"
 graphviz = { path = "../libgraphviz" }
 log = "0.4"
 log_settings = "0.1.1"
-polonius-engine = "0.1.1"
+polonius-engine = "0.4.0"
 rustc = { path = "../librustc" }
 rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs
index 070dc1d09bf..5631356dc1e 100644
--- a/src/librustc_mir/borrow_check/flows.rs
+++ b/src/librustc_mir/borrow_check/flows.rs
@@ -14,15 +14,22 @@
 //! but is not as ugly as it is right now.
 
 use rustc::mir::{BasicBlock, Location};
+use rustc::ty::RegionVid;
 use rustc_data_structures::indexed_set::Iter;
 
-use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
+use borrow_check::location::LocationIndex;
+
+use polonius_engine::Output;
+
+use dataflow::move_paths::indexes::BorrowIndex;
+use dataflow::move_paths::HasMoveData;
+use dataflow::Borrows;
 use dataflow::{EverInitializedPlaces, MovingOutStatements};
-use dataflow::{Borrows};
 use dataflow::{FlowAtLocation, FlowsAtLocation};
-use dataflow::move_paths::HasMoveData;
-use dataflow::move_paths::indexes::BorrowIndex;
+use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
+use either::Either;
 use std::fmt;
+use std::rc::Rc;
 
 // (forced to be `pub` due to its use as an associated type below.)
 crate struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
@@ -31,6 +38,9 @@ crate struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
     pub uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
     pub move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
     pub ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
+
+    /// Polonius Output
+    pub polonius_output: Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
 }
 
 impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
@@ -40,6 +50,7 @@ impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
         uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
         move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
         ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
+        polonius_output: Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
     ) -> Self {
         Flows {
             borrows,
@@ -47,11 +58,19 @@ impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
             uninits,
             move_outs,
             ever_inits,
+            polonius_output,
         }
     }
 
-    crate fn borrows_in_scope(&self) -> impl Iterator<Item = BorrowIndex> + '_ {
-        self.borrows.iter_incoming()
+    crate fn borrows_in_scope(
+        &self,
+        location: LocationIndex,
+    ) -> impl Iterator<Item = BorrowIndex> + '_ {
+        if let Some(ref polonius) = self.polonius_output {
+            Either::Left(polonius.errors_at(location).iter().cloned())
+        } else {
+            Either::Right(self.borrows.iter_incoming())
+        }
     }
 
     crate fn with_outgoing_borrows(&self, op: impl FnOnce(Iter<BorrowIndex>)) {
@@ -66,7 +85,7 @@ macro_rules! each_flow {
         FlowAtLocation::$meth(&mut $this.uninits, $arg);
         FlowAtLocation::$meth(&mut $this.move_outs, $arg);
         FlowAtLocation::$meth(&mut $this.ever_inits, $arg);
-    }
+    };
 }
 
 impl<'b, 'gcx, 'tcx> FlowsAtLocation for Flows<'b, 'gcx, 'tcx> {
@@ -134,8 +153,7 @@ impl<'b, 'gcx, 'tcx> fmt::Display for Flows<'b, 'gcx, 'tcx> {
                 s.push_str(", ");
             };
             saw_one = true;
-            let move_path =
-                &self.uninits.operator().move_data().move_paths[mpi_uninit];
+            let move_path = &self.uninits.operator().move_data().move_paths[mpi_uninit];
             s.push_str(&format!("{}", move_path));
         });
         s.push_str("] ");
@@ -159,8 +177,7 @@ impl<'b, 'gcx, 'tcx> fmt::Display for Flows<'b, 'gcx, 'tcx> {
                 s.push_str(", ");
             };
             saw_one = true;
-            let ever_init =
-                &self.ever_inits.operator().move_data().inits[mpi_ever_init];
+            let ever_init = &self.ever_inits.operator().move_data().inits[mpi_ever_init];
             s.push_str(&format!("{:?}", ever_init));
         });
         s.push_str("]");
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index ffa6fc9daec..9bfba219ccd 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -198,7 +198,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     let borrow_set = Rc::new(BorrowSet::build(tcx, mir));
 
     // If we are in non-lexical mode, compute the non-lexical lifetimes.
-    let (regioncx, opt_closure_req) = nll::compute_regions(
+    let (regioncx, polonius_output, opt_closure_req) = nll::compute_regions(
         infcx,
         def_id,
         free_regions,
@@ -259,6 +259,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         flow_uninits,
         flow_move_outs,
         flow_ever_inits,
+        polonius_output,
     );
 
     mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer
@@ -936,6 +937,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         let mut error_reported = false;
         let tcx = self.tcx;
         let mir = self.mir;
+        let location_table = &LocationTable::new(mir);
+        let location = location_table.start_index(context.loc);
         let borrow_set = self.borrow_set.clone();
         each_borrow_involving_path(
             self,
@@ -944,7 +947,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             context,
             (sd, place_span.0),
             &borrow_set,
-            flow_state.borrows_in_scope(),
+            flow_state.borrows_in_scope(location),
             |this, borrow_index, borrow|
             match (rw, borrow.kind) {
                 // Obviously an activation is compatible with its own
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index a91789733a9..ec1f3dbaeeb 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -9,8 +9,9 @@
 // except according to those terms.
 
 use borrow_check::borrow_set::BorrowSet;
-use borrow_check::location::LocationTable;
+use borrow_check::location::{LocationIndex, LocationTable};
 use borrow_check::nll::facts::AllFactsExt;
+use dataflow::indexes::BorrowIndex;
 use dataflow::move_paths::MoveData;
 use dataflow::FlowAtLocation;
 use dataflow::MaybeInitializedPlaces;
@@ -23,22 +24,24 @@ use std::collections::BTreeSet;
 use std::fmt::Debug;
 use std::io;
 use std::path::PathBuf;
+use std::rc::Rc;
 use transform::MirSource;
 use util::liveness::{LivenessResults, LocalSet};
 
 use self::mir_util::PassWhere;
+use polonius_engine::{Algorithm, Output};
 use util as mir_util;
 use util::pretty::{self, ALIGN};
 
 mod constraint_generation;
 pub mod explain_borrow;
 mod facts;
+mod invalidation;
 crate mod region_infer;
 mod renumber;
 mod subtype_constraint_generation;
 crate mod type_check;
 mod universal_regions;
-mod invalidation;
 
 use self::facts::AllFacts;
 use self::region_infer::RegionInferenceContext;
@@ -83,6 +86,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     borrow_set: &BorrowSet<'tcx>,
 ) -> (
     RegionInferenceContext<'tcx>,
+    Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
     Option<ClosureRegionRequirements<'gcx>>,
 ) {
     // Run the MIR type-checker.
@@ -98,7 +102,9 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
         move_data,
     );
 
-    let mut all_facts = if infcx.tcx.sess.opts.debugging_opts.nll_facts {
+    let mut all_facts = if infcx.tcx.sess.opts.debugging_opts.nll_facts
+        || infcx.tcx.sess.opts.debugging_opts.polonius
+    {
         Some(AllFacts::default())
     } else {
         None
@@ -113,8 +119,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     // Create the region inference context, taking ownership of the region inference
     // data that was contained in `infcx`.
     let var_origins = infcx.take_region_var_origins();
-    let mut regioncx =
-        RegionInferenceContext::new(var_origins, universal_regions, mir);
+    let mut regioncx = RegionInferenceContext::new(var_origins, universal_regions, mir);
 
     // Generate various constraints.
     subtype_constraint_generation::generate(
@@ -138,15 +143,28 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
         location_table,
         &mir,
         def_id,
-        borrow_set
+        borrow_set,
     );
 
     // Dump facts if requested.
-    if let Some(all_facts) = all_facts {
-        let def_path = infcx.tcx.hir.def_path(def_id);
-        let dir_path = PathBuf::from("nll-facts").join(def_path.to_filename_friendly_no_crate());
-        all_facts.write_to_dir(dir_path, location_table).unwrap();
-    }
+    let polonius_output = all_facts.and_then(|all_facts| {
+        if infcx.tcx.sess.opts.debugging_opts.nll_facts {
+            let def_path = infcx.tcx.hir.def_path(def_id);
+            let dir_path =
+                PathBuf::from("nll-facts").join(def_path.to_filename_friendly_no_crate());
+            all_facts.write_to_dir(dir_path, location_table).unwrap();
+        }
+
+        if infcx.tcx.sess.opts.debugging_opts.polonius {
+            Some(Rc::new(Output::compute(
+                &all_facts,
+                Algorithm::DatafrogOpt,
+                false,
+            )))
+        } else {
+            None
+        }
+    });
 
     // Solve the region constraints.
     let closure_region_requirements = regioncx.solve(infcx, &mir, def_id);
@@ -166,7 +184,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     // information
     dump_annotation(infcx, &mir, def_id, &regioncx, &closure_region_requirements);
 
-    (regioncx, closure_region_requirements)
+    (regioncx, polonius_output, closure_region_requirements)
 }
 
 fn dump_mir_results<'a, 'gcx, 'tcx>(
@@ -181,7 +199,8 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
         return;
     }
 
-    let regular_liveness_per_location: FxHashMap<_, _> = mir.basic_blocks()
+    let regular_liveness_per_location: FxHashMap<_, _> = mir
+        .basic_blocks()
         .indices()
         .flat_map(|bb| {
             let mut results = vec![];
@@ -194,7 +213,8 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
         })
         .collect();
 
-    let drop_liveness_per_location: FxHashMap<_, _> = mir.basic_blocks()
+    let drop_liveness_per_location: FxHashMap<_, _> = mir
+        .basic_blocks()
         .indices()
         .flat_map(|bb| {
             let mut results = vec![];
@@ -207,47 +227,55 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
         })
         .collect();
 
-    mir_util::dump_mir(infcx.tcx, None, "nll", &0, source, mir, |pass_where, out| {
-        match pass_where {
-            // Before the CFG, dump out the values for each region variable.
-            PassWhere::BeforeCFG => {
-                regioncx.dump_mir(out)?;
-
-                if let Some(closure_region_requirements) = closure_region_requirements {
-                    writeln!(out, "|")?;
-                    writeln!(out, "| Free Region Constraints")?;
-                    for_each_region_constraint(closure_region_requirements, &mut |msg| {
-                        writeln!(out, "| {}", msg)
-                    })?;
+    mir_util::dump_mir(
+        infcx.tcx,
+        None,
+        "nll",
+        &0,
+        source,
+        mir,
+        |pass_where, out| {
+            match pass_where {
+                // Before the CFG, dump out the values for each region variable.
+                PassWhere::BeforeCFG => {
+                    regioncx.dump_mir(out)?;
+
+                    if let Some(closure_region_requirements) = closure_region_requirements {
+                        writeln!(out, "|")?;
+                        writeln!(out, "| Free Region Constraints")?;
+                        for_each_region_constraint(closure_region_requirements, &mut |msg| {
+                            writeln!(out, "| {}", msg)
+                        })?;
+                    }
+                }
+
+                // Before each basic block, dump out the values
+                // that are live on entry to the basic block.
+                PassWhere::BeforeBlock(bb) => {
+                    let s = live_variable_set(&liveness.regular.ins[bb], &liveness.drop.ins[bb]);
+                    writeln!(out, "    | Live variables on entry to {:?}: {}", bb, s)?;
                 }
-            }
 
-            // Before each basic block, dump out the values
-            // that are live on entry to the basic block.
-            PassWhere::BeforeBlock(bb) => {
-                let s = live_variable_set(&liveness.regular.ins[bb], &liveness.drop.ins[bb]);
-                writeln!(out, "    | Live variables on entry to {:?}: {}", bb, s)?;
-            }
+                PassWhere::BeforeLocation(location) => {
+                    let s = live_variable_set(
+                        &regular_liveness_per_location[&location],
+                        &drop_liveness_per_location[&location],
+                    );
+                    writeln!(
+                        out,
+                        "{:ALIGN$} | Live variables on entry to {:?}: {}",
+                        "",
+                        location,
+                        s,
+                        ALIGN = ALIGN
+                    )?;
+                }
 
-            PassWhere::BeforeLocation(location) => {
-                let s = live_variable_set(
-                    &regular_liveness_per_location[&location],
-                    &drop_liveness_per_location[&location],
-                );
-                writeln!(
-                    out,
-                    "{:ALIGN$} | Live variables on entry to {:?}: {}",
-                    "",
-                    location,
-                    s,
-                    ALIGN = ALIGN
-                )?;
+                PassWhere::AfterLocation(_) | PassWhere::AfterCFG => {}
             }
-
-            PassWhere::AfterLocation(_) | PassWhere::AfterCFG => {}
-        }
-        Ok(())
-    });
+            Ok(())
+        },
+    );
 
     // Also dump the inference graph constraints as a graphviz file.
     let _: io::Result<()> = do catch {
@@ -278,7 +306,8 @@ fn dump_annotation<'a, 'gcx, 'tcx>(
     // better.
 
     if let Some(closure_region_requirements) = closure_region_requirements {
-        let mut err = tcx.sess
+        let mut err = tcx
+            .sess
             .diagnostic()
             .span_note_diag(mir.span, "External requirements");
 
@@ -298,7 +327,8 @@ fn dump_annotation<'a, 'gcx, 'tcx>(
 
         err.emit();
     } else {
-        let mut err = tcx.sess
+        let mut err = tcx
+            .sess
             .diagnostic()
             .span_note_diag(mir.span, "No external requirements");
         regioncx.annotate(&mut err);
@@ -317,8 +347,7 @@ fn for_each_region_constraint(
         };
         with_msg(&format!(
             "where {:?}: {:?}",
-            subject,
-            req.outlived_free_region,
+            subject, req.outlived_free_region,
         ))?;
     }
     Ok(())
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index ace4709ba1d..34eb444fdc0 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -38,6 +38,7 @@ extern crate arena;
 #[macro_use]
 extern crate bitflags;
 #[macro_use] extern crate log;
+extern crate either;
 extern crate graphviz as dot;
 extern crate polonius_engine;
 #[macro_use]
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 86a600ddc2f..a4eb784fa7d 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -73,6 +73,7 @@ static WHITELIST: &'static [Crate] = &[
     Crate("crossbeam-deque"),
     Crate("crossbeam-epoch"),
     Crate("crossbeam-utils"),
+    Crate("datafrog"),
     Crate("either"),
     Crate("ena"),
     Crate("env_logger"),