about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-07-13 10:15:40 +0000
committerbors <bors@rust-lang.org>2019-07-13 10:15:40 +0000
commit6b468c6360cba002ba1e97b70cf51223a498442e (patch)
tree6af315a024a19f49c8a15242144ade988609a548
parent4a95e9704de0eeaecba55df102c1129e79a3a929 (diff)
parent9d3c59d69750e07d9446339c4b733c925d3571bc (diff)
downloadrust-6b468c6360cba002ba1e97b70cf51223a498442e.tar.gz
rust-6b468c6360cba002ba1e97b70cf51223a498442e.zip
Auto merge of #60266 - albins:polonius-liveness, r=nikomatsakis
Fact generation for liveness calculations in Polonius

This PR tracks ongoing work to extend `rustc` with support for generating variable use, definition, and later also drop output for the Polonius solver, the whole of which is being tracked in [Polonius Issue #104](https://github.com/rust-lang/polonius/issues/104).
-rw-r--r--Cargo.lock8
-rw-r--r--src/librustc/Cargo.toml2
-rw-r--r--src/librustc/mir/mod.rs736
-rw-r--r--src/librustc_mir/Cargo.toml2
-rw-r--r--src/librustc_mir/borrow_check/flows.rs17
-rw-r--r--src/librustc_mir/borrow_check/nll/facts.rs54
-rw-r--r--src/librustc_mir/borrow_check/nll/mod.rs4
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs15
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs94
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs145
10 files changed, 449 insertions, 628 deletions
diff --git a/Cargo.lock b/Cargo.lock
index cee2b385648..5a20e6e102b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2214,7 +2214,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "polonius-engine"
-version = "0.7.0"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "datafrog 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2686,7 +2686,7 @@ dependencies = [
  "measureme 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "polonius-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "polonius-engine 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_apfloat 0.0.0",
@@ -3203,7 +3203,7 @@ dependencies = [
  "graphviz 0.0.0",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "polonius-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "polonius-engine 0.9.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",
@@ -4695,7 +4695,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662"
 "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
 "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
-"checksum polonius-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b24942fee141ea45628484a453762bb7e515099c3ec05fbeb76b7bf57b1aeed"
+"checksum polonius-engine 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6b8a5defa2aef9ba4999aaa745fbc01c622ecea35964a306adc3e44be4f3b5b"
 "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 pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61"
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index b6f3bc62dfd..1677ef4b607 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -19,9 +19,9 @@ lazy_static = "1.0.0"
 num_cpus = "1.0"
 scoped-tls = "1.0"
 log = { version = "0.4", features = ["release_max_level_info", "std"] }
-polonius-engine = "0.7.0"
 rustc-rayon = "0.2.0"
 rustc-rayon-core = "0.2.0"
+polonius-engine  = "0.9.0"
 rustc_apfloat = { path = "../librustc_apfloat" }
 rustc_target = { path = "../librustc_target" }
 rustc_macros = { path = "../librustc_macros" }
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index ff868bf2a2a..783964c701a 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -9,6 +9,17 @@ use crate::hir::def_id::DefId;
 use crate::hir::{self, InlineAsm as HirInlineAsm};
 use crate::mir::interpret::{ConstValue, InterpError, Scalar};
 use crate::mir::visit::MirVisitable;
+use crate::rustc_serialize as serialize;
+use crate::ty::adjustment::PointerCast;
+use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+use crate::ty::layout::VariantIdx;
+use crate::ty::print::{FmtPrinter, Printer};
+use crate::ty::subst::{Subst, SubstsRef};
+use crate::ty::{
+    self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt,
+    UserTypeAnnotationIndex,
+};
+use polonius_engine::Atom;
 use rustc_data_structures::bit_set::BitMatrix;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::graph::dominators::{dominators, Dominators};
@@ -17,10 +28,9 @@ use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::sync::MappedReadGuard;
 use rustc_macros::HashStable;
-use crate::rustc_serialize::{self as serialize};
 use smallvec::SmallVec;
 use std::borrow::Cow;
-use std::fmt::{self, Debug, Formatter, Write, Display};
+use std::fmt::{self, Debug, Display, Formatter, Write};
 use std::iter::FusedIterator;
 use std::ops::{Index, IndexMut};
 use std::slice;
@@ -29,15 +39,6 @@ use std::{iter, mem, option, u32};
 use syntax::ast::Name;
 use syntax::symbol::{InternedString, Symbol};
 use syntax_pos::{Span, DUMMY_SP};
-use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
-use crate::ty::subst::{Subst, SubstsRef};
-use crate::ty::layout::VariantIdx;
-use crate::ty::{
-    self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt,
-    UserTypeAnnotationIndex,
-};
-use crate::ty::print::{FmtPrinter, Printer};
-use crate::ty::adjustment::{PointerCast};
 
 pub use crate::mir::interpret::AssertMessage;
 
@@ -224,10 +225,7 @@ impl<'tcx> Body<'tcx> {
     #[inline]
     pub fn basic_blocks_and_local_decls_mut(
         &mut self,
-    ) -> (
-        &mut IndexVec<BasicBlock, BasicBlockData<'tcx>>,
-        &mut LocalDecls<'tcx>,
-    ) {
+    ) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) {
         self.cache.invalidate();
         (&mut self.basic_blocks, &mut self.local_decls)
     }
@@ -259,16 +257,10 @@ impl<'tcx> Body<'tcx> {
         let if_not_zero_locations = if loc.statement_index == 0 {
             None
         } else {
-            Some(Location {
-                block: loc.block,
-                statement_index: loc.statement_index - 1,
-            })
+            Some(Location { block: loc.block, statement_index: loc.statement_index - 1 })
         };
 
-        if_zero_locations
-            .into_iter()
-            .flatten()
-            .chain(if_not_zero_locations)
+        if_zero_locations.into_iter().flatten().chain(if_not_zero_locations)
     }
 
     #[inline]
@@ -406,10 +398,7 @@ impl<'tcx> Body<'tcx> {
 
     /// Gets the location of the terminator for the given block
     pub fn terminator_loc(&self, bb: BasicBlock) -> Location {
-        Location {
-            block: bb,
-            statement_index: self[bb].statements.len(),
-        }
+        Location { block: bb, statement_index: self[bb].statements.len() }
     }
 }
 
@@ -508,8 +497,9 @@ impl From<Mutability> for hir::Mutability {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd,
-         Ord, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(
+    Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, HashStable,
+)]
 pub enum BorrowKind {
     /// Data must be immutable and is aliasable.
     Shared,
@@ -600,6 +590,12 @@ newtype_index! {
     }
 }
 
+impl Atom for Local {
+    fn index(self) -> usize {
+        Idx::index(self)
+    }
+}
+
 /// Classifies locals into categories. See `Body::local_kind`.
 #[derive(PartialEq, Eq, Debug, HashStable)]
 pub enum LocalKind {
@@ -658,7 +654,7 @@ pub enum ImplicitSelfKind {
     MutRef,
     /// Represents when a function does not have a self argument or
     /// when a function has a `self: X` argument.
-    None
+    None,
 }
 
 CloneTypeFoldableAndLiftImpls! { BindingForm<'tcx>, }
@@ -889,8 +885,7 @@ impl<'tcx> LocalDecl<'tcx> {
                 pat_span: _,
             }))) => true,
 
-            Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(ImplicitSelfKind::Imm)))
-                => true,
+            Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(ImplicitSelfKind::Imm))) => true,
 
             _ => false,
         }
@@ -959,21 +954,13 @@ impl<'tcx> LocalDecl<'tcx> {
     }
 
     #[inline]
-    fn new_local(
-        ty: Ty<'tcx>,
-        mutability: Mutability,
-        internal: bool,
-        span: Span,
-    ) -> Self {
+    fn new_local(ty: Ty<'tcx>, mutability: Mutability, internal: bool, span: Span) -> Self {
         LocalDecl {
             mutability,
             ty,
             user_ty: UserTypeProjections::none(),
             name: None,
-            source_info: SourceInfo {
-                span,
-                scope: OUTERMOST_SOURCE_SCOPE,
-            },
+            source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
             visibility_scope: OUTERMOST_SOURCE_SCOPE,
             internal,
             is_user_variable: None,
@@ -990,10 +977,7 @@ impl<'tcx> LocalDecl<'tcx> {
             mutability: Mutability::Mut,
             ty: return_ty,
             user_ty: UserTypeProjections::none(),
-            source_info: SourceInfo {
-                span,
-                scope: OUTERMOST_SOURCE_SCOPE,
-            },
+            source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
             visibility_scope: OUTERMOST_SOURCE_SCOPE,
             internal: false,
             is_block_tail: None,
@@ -1025,10 +1009,7 @@ newtype_index! {
 
 impl BasicBlock {
     pub fn start_location(self) -> Location {
-        Location {
-            block: self,
-            statement_index: 0,
-        }
+        Location { block: self, statement_index: 0 }
     }
 }
 
@@ -1111,11 +1092,7 @@ pub enum TerminatorKind<'tcx> {
     Unreachable,
 
     /// Drop the Place
-    Drop {
-        location: Place<'tcx>,
-        target: BasicBlock,
-        unwind: Option<BasicBlock>,
-    },
+    Drop { location: Place<'tcx>, target: BasicBlock, unwind: Option<BasicBlock> },
 
     /// Drop the Place and assign the new value over it. This ensures
     /// that the assignment to `P` occurs *even if* the destructor for
@@ -1263,80 +1240,27 @@ impl<'tcx> TerminatorKind<'tcx> {
             | GeneratorDrop
             | Return
             | Unreachable
-            | Call {
-                destination: None,
-                cleanup: None,
-                ..
-            } => None.into_iter().chain(&[]),
+            | Call { destination: None, cleanup: None, .. } => None.into_iter().chain(&[]),
             Goto { target: ref t }
-            | Call {
-                destination: None,
-                cleanup: Some(ref t),
-                ..
-            }
-            | Call {
-                destination: Some((_, ref t)),
-                cleanup: None,
-                ..
-            }
-            | Yield {
-                resume: ref t,
-                drop: None,
-                ..
-            }
-            | DropAndReplace {
-                target: ref t,
-                unwind: None,
-                ..
-            }
-            | Drop {
-                target: ref t,
-                unwind: None,
-                ..
-            }
-            | Assert {
-                target: ref t,
-                cleanup: None,
-                ..
+            | Call { destination: None, cleanup: Some(ref t), .. }
+            | Call { destination: Some((_, ref t)), cleanup: None, .. }
+            | Yield { resume: ref t, drop: None, .. }
+            | DropAndReplace { target: ref t, unwind: None, .. }
+            | Drop { target: ref t, unwind: None, .. }
+            | Assert { target: ref t, cleanup: None, .. }
+            | FalseUnwind { real_target: ref t, unwind: None } => Some(t).into_iter().chain(&[]),
+            Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. }
+            | Yield { resume: ref t, drop: Some(ref u), .. }
+            | DropAndReplace { target: ref t, unwind: Some(ref u), .. }
+            | Drop { target: ref t, unwind: Some(ref u), .. }
+            | Assert { target: ref t, cleanup: Some(ref u), .. }
+            | FalseUnwind { real_target: ref t, unwind: Some(ref u) } => {
+                Some(t).into_iter().chain(slice::from_ref(u))
             }
-            | FalseUnwind {
-                real_target: ref t,
-                unwind: None,
-            } => Some(t).into_iter().chain(&[]),
-            Call {
-                destination: Some((_, ref t)),
-                cleanup: Some(ref u),
-                ..
-            }
-            | Yield {
-                resume: ref t,
-                drop: Some(ref u),
-                ..
-            }
-            | DropAndReplace {
-                target: ref t,
-                unwind: Some(ref u),
-                ..
-            }
-            | Drop {
-                target: ref t,
-                unwind: Some(ref u),
-                ..
-            }
-            | Assert {
-                target: ref t,
-                cleanup: Some(ref u),
-                ..
-            }
-            | FalseUnwind {
-                real_target: ref t,
-                unwind: Some(ref u),
-            } => Some(t).into_iter().chain(slice::from_ref(u)),
             SwitchInt { ref targets, .. } => None.into_iter().chain(&targets[..]),
-            FalseEdges {
-                ref real_target,
-                ref imaginary_target,
-            } => Some(real_target).into_iter().chain(slice::from_ref(imaginary_target)),
+            FalseEdges { ref real_target, ref imaginary_target } => {
+                Some(real_target).into_iter().chain(slice::from_ref(imaginary_target))
+            }
         }
     }
 
@@ -1348,84 +1272,29 @@ impl<'tcx> TerminatorKind<'tcx> {
             | GeneratorDrop
             | Return
             | Unreachable
-            | Call {
-                destination: None,
-                cleanup: None,
-                ..
-            } => None.into_iter().chain(&mut []),
+            | Call { destination: None, cleanup: None, .. } => None.into_iter().chain(&mut []),
             Goto { target: ref mut t }
-            | Call {
-                destination: None,
-                cleanup: Some(ref mut t),
-                ..
-            }
-            | Call {
-                destination: Some((_, ref mut t)),
-                cleanup: None,
-                ..
+            | Call { destination: None, cleanup: Some(ref mut t), .. }
+            | Call { destination: Some((_, ref mut t)), cleanup: None, .. }
+            | Yield { resume: ref mut t, drop: None, .. }
+            | DropAndReplace { target: ref mut t, unwind: None, .. }
+            | Drop { target: ref mut t, unwind: None, .. }
+            | Assert { target: ref mut t, cleanup: None, .. }
+            | FalseUnwind { real_target: ref mut t, unwind: None } => {
+                Some(t).into_iter().chain(&mut [])
             }
-            | Yield {
-                resume: ref mut t,
-                drop: None,
-                ..
+            Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. }
+            | Yield { resume: ref mut t, drop: Some(ref mut u), .. }
+            | DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. }
+            | Drop { target: ref mut t, unwind: Some(ref mut u), .. }
+            | Assert { target: ref mut t, cleanup: Some(ref mut u), .. }
+            | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => {
+                Some(t).into_iter().chain(slice::from_mut(u))
             }
-            | DropAndReplace {
-                target: ref mut t,
-                unwind: None,
-                ..
+            SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets[..]),
+            FalseEdges { ref mut real_target, ref mut imaginary_target } => {
+                Some(real_target).into_iter().chain(slice::from_mut(imaginary_target))
             }
-            | Drop {
-                target: ref mut t,
-                unwind: None,
-                ..
-            }
-            | Assert {
-                target: ref mut t,
-                cleanup: None,
-                ..
-            }
-            | FalseUnwind {
-                real_target: ref mut t,
-                unwind: None,
-            } => Some(t).into_iter().chain(&mut []),
-            Call {
-                destination: Some((_, ref mut t)),
-                cleanup: Some(ref mut u),
-                ..
-            }
-            | Yield {
-                resume: ref mut t,
-                drop: Some(ref mut u),
-                ..
-            }
-            | DropAndReplace {
-                target: ref mut t,
-                unwind: Some(ref mut u),
-                ..
-            }
-            | Drop {
-                target: ref mut t,
-                unwind: Some(ref mut u),
-                ..
-            }
-            | Assert {
-                target: ref mut t,
-                cleanup: Some(ref mut u),
-                ..
-            }
-            | FalseUnwind {
-                real_target: ref mut t,
-                unwind: Some(ref mut u),
-            } => Some(t).into_iter().chain(slice::from_mut(u)),
-            SwitchInt {
-                ref mut targets, ..
-            } => None.into_iter().chain(&mut targets[..]),
-            FalseEdges {
-                ref mut real_target,
-                ref mut imaginary_target,
-            } => Some(real_target)
-                .into_iter()
-                .chain(slice::from_mut(imaginary_target)),
         }
     }
 
@@ -1440,14 +1309,8 @@ impl<'tcx> TerminatorKind<'tcx> {
             | TerminatorKind::Yield { .. }
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::FalseEdges { .. } => None,
-            TerminatorKind::Call {
-                cleanup: ref unwind,
-                ..
-            }
-            | TerminatorKind::Assert {
-                cleanup: ref unwind,
-                ..
-            }
+            TerminatorKind::Call { cleanup: ref unwind, .. }
+            | TerminatorKind::Assert { cleanup: ref unwind, .. }
             | TerminatorKind::DropAndReplace { ref unwind, .. }
             | TerminatorKind::Drop { ref unwind, .. }
             | TerminatorKind::FalseUnwind { ref unwind, .. } => Some(unwind),
@@ -1465,14 +1328,8 @@ impl<'tcx> TerminatorKind<'tcx> {
             | TerminatorKind::Yield { .. }
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::FalseEdges { .. } => None,
-            TerminatorKind::Call {
-                cleanup: ref mut unwind,
-                ..
-            }
-            | TerminatorKind::Assert {
-                cleanup: ref mut unwind,
-                ..
-            }
+            TerminatorKind::Call { cleanup: ref mut unwind, .. }
+            | TerminatorKind::Assert { cleanup: ref mut unwind, .. }
             | TerminatorKind::DropAndReplace { ref mut unwind, .. }
             | TerminatorKind::Drop { ref mut unwind, .. }
             | TerminatorKind::FalseUnwind { ref mut unwind, .. } => Some(unwind),
@@ -1482,11 +1339,7 @@ impl<'tcx> TerminatorKind<'tcx> {
 
 impl<'tcx> BasicBlockData<'tcx> {
     pub fn new(terminator: Option<Terminator<'tcx>>) -> BasicBlockData<'tcx> {
-        BasicBlockData {
-            statements: vec![],
-            terminator,
-            is_cleanup: false,
-        }
+        BasicBlockData { statements: vec![], terminator, is_cleanup: false }
     }
 
     /// Accessor for terminator.
@@ -1548,10 +1401,7 @@ impl<'tcx> BasicBlockData<'tcx> {
         self.statements.resize(
             gap.end,
             Statement {
-                source_info: SourceInfo {
-                    span: DUMMY_SP,
-                    scope: OUTERMOST_SOURCE_SCOPE,
-                },
+                source_info: SourceInfo { span: DUMMY_SP, scope: OUTERMOST_SOURCE_SCOPE },
                 kind: StatementKind::Nop,
             },
         );
@@ -1610,9 +1460,7 @@ impl<'tcx> TerminatorKind<'tcx> {
         use self::TerminatorKind::*;
         match *self {
             Goto { .. } => write!(fmt, "goto"),
-            SwitchInt {
-                discr: ref place, ..
-            } => write!(fmt, "switchInt({:?})", place),
+            SwitchInt { discr: ref place, .. } => write!(fmt, "switchInt({:?})", place),
             Return => write!(fmt, "return"),
             GeneratorDrop => write!(fmt, "generator_drop"),
             Resume => write!(fmt, "resume"),
@@ -1620,17 +1468,10 @@ impl<'tcx> TerminatorKind<'tcx> {
             Yield { ref value, .. } => write!(fmt, "_1 = suspend({:?})", value),
             Unreachable => write!(fmt, "unreachable"),
             Drop { ref location, .. } => write!(fmt, "drop({:?})", location),
-            DropAndReplace {
-                ref location,
-                ref value,
-                ..
-            } => write!(fmt, "replace({:?} <- {:?})", location, value),
-            Call {
-                ref func,
-                ref args,
-                ref destination,
-                ..
-            } => {
+            DropAndReplace { ref location, ref value, .. } => {
+                write!(fmt, "replace({:?} <- {:?})", location, value)
+            }
+            Call { ref func, ref args, ref destination, .. } => {
                 if let Some((ref destination, _)) = *destination {
                     write!(fmt, "{:?} = ", destination)?;
                 }
@@ -1643,12 +1484,7 @@ impl<'tcx> TerminatorKind<'tcx> {
                 }
                 write!(fmt, ")")
             }
-            Assert {
-                ref cond,
-                expected,
-                ref msg,
-                ..
-            } => {
+            Assert { ref cond, expected, ref msg, .. } => {
                 write!(fmt, "assert(")?;
                 if !expected {
                     write!(fmt, "!")?;
@@ -1666,69 +1502,41 @@ impl<'tcx> TerminatorKind<'tcx> {
         match *self {
             Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
             Goto { .. } => vec!["".into()],
-            SwitchInt {
-                ref values,
-                switch_ty,
-                ..
-            } => {
-                ty::tls::with(|tcx| {
-                    let param_env = ty::ParamEnv::empty();
-                    let switch_ty = tcx.lift_to_global(&switch_ty).unwrap();
-                    let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size;
-                    values
-                        .iter()
-                        .map(|&u| {
-                            tcx.mk_const(ty::Const {
-                                val: ConstValue::Scalar(
-                                    Scalar::from_uint(u, size).into(),
-                                ),
-                                ty: switch_ty,
-                            }).to_string().into()
-                        }).chain(iter::once("otherwise".into()))
-                        .collect()
-                })
+            SwitchInt { ref values, switch_ty, .. } => ty::tls::with(|tcx| {
+                let param_env = ty::ParamEnv::empty();
+                let switch_ty = tcx.lift_to_global(&switch_ty).unwrap();
+                let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size;
+                values
+                    .iter()
+                    .map(|&u| {
+                        tcx.mk_const(ty::Const {
+                            val: ConstValue::Scalar(Scalar::from_uint(u, size).into()),
+                            ty: switch_ty,
+                        })
+                        .to_string()
+                        .into()
+                    })
+                    .chain(iter::once("otherwise".into()))
+                    .collect()
+            }),
+            Call { destination: Some(_), cleanup: Some(_), .. } => {
+                vec!["return".into(), "unwind".into()]
             }
-            Call {
-                destination: Some(_),
-                cleanup: Some(_),
-                ..
-            } => vec!["return".into(), "unwind".into()],
-            Call {
-                destination: Some(_),
-                cleanup: None,
-                ..
-            } => vec!["return".into()],
-            Call {
-                destination: None,
-                cleanup: Some(_),
-                ..
-            } => vec!["unwind".into()],
-            Call {
-                destination: None,
-                cleanup: None,
-                ..
-            } => vec![],
+            Call { destination: Some(_), cleanup: None, .. } => vec!["return".into()],
+            Call { destination: None, cleanup: Some(_), .. } => vec!["unwind".into()],
+            Call { destination: None, cleanup: None, .. } => vec![],
             Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
             Yield { drop: None, .. } => vec!["resume".into()],
             DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => {
                 vec!["return".into()]
             }
-            DropAndReplace {
-                unwind: Some(_), ..
+            DropAndReplace { unwind: Some(_), .. } | Drop { unwind: Some(_), .. } => {
+                vec!["return".into(), "unwind".into()]
             }
-            | Drop {
-                unwind: Some(_), ..
-            } => vec!["return".into(), "unwind".into()],
             Assert { cleanup: None, .. } => vec!["".into()],
             Assert { .. } => vec!["success".into(), "unwind".into()],
-            FalseEdges {
-                ..
-            } => {
-                vec!["real".into(), "imaginary".into()]
-            }
-            FalseUnwind {
-                unwind: Some(_), ..
-            } => vec!["real".into(), "cleanup".into()],
+            FalseEdges { .. } => vec!["real".into(), "imaginary".into()],
+            FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()],
             FalseUnwind { unwind: None, .. } => vec!["real".into()],
         }
     }
@@ -1778,10 +1586,7 @@ pub enum StatementKind<'tcx> {
     FakeRead(FakeReadCause, Place<'tcx>),
 
     /// Write the discriminant for a variant to the enum Place.
-    SetDiscriminant {
-        place: Place<'tcx>,
-        variant_index: VariantIdx,
-    },
+    SetDiscriminant { place: Place<'tcx>, variant_index: VariantIdx },
 
     /// Start a live range for the storage of the local.
     StorageLive(Local),
@@ -1878,24 +1683,25 @@ impl<'tcx> Debug for Statement<'tcx> {
         match self.kind {
             Assign(ref place, ref rv) => write!(fmt, "{:?} = {:?}", place, rv),
             FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place),
-            Retag(ref kind, ref place) =>
-                write!(fmt, "Retag({}{:?})",
-                    match kind {
-                        RetagKind::FnEntry => "[fn entry] ",
-                        RetagKind::TwoPhase => "[2phase] ",
-                        RetagKind::Raw => "[raw] ",
-                        RetagKind::Default => "",
-                    },
-                    place,
-                ),
+            Retag(ref kind, ref place) => write!(
+                fmt,
+                "Retag({}{:?})",
+                match kind {
+                    RetagKind::FnEntry => "[fn entry] ",
+                    RetagKind::TwoPhase => "[2phase] ",
+                    RetagKind::Raw => "[raw] ",
+                    RetagKind::Default => "",
+                },
+                place,
+            ),
             StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place),
             StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place),
-            SetDiscriminant {
-                ref place,
-                variant_index,
-            } => write!(fmt, "discriminant({:?}) = {:?}", place, variant_index),
-            InlineAsm(ref asm) =>
-                write!(fmt, "asm!({:?} : {:?} : {:?})", asm.asm, asm.outputs, asm.inputs),
+            SetDiscriminant { ref place, variant_index } => {
+                write!(fmt, "discriminant({:?}) = {:?}", place, variant_index)
+            }
+            InlineAsm(ref asm) => {
+                write!(fmt, "asm!({:?} : {:?} : {:?})", asm.asm, asm.outputs, asm.inputs)
+            }
             AscribeUserType(ref place, ref variance, ref c_ty) => {
                 write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty)
             }
@@ -1909,7 +1715,9 @@ impl<'tcx> Debug for Statement<'tcx> {
 
 /// A path to a value; something that can be evaluated without
 /// changing or disturbing program state.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(
+    Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable,
+)]
 pub enum Place<'tcx> {
     Base(PlaceBase<'tcx>),
 
@@ -1917,7 +1725,9 @@ pub enum Place<'tcx> {
     Projection(Box<Projection<'tcx>>),
 }
 
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(
+    Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable,
+)]
 pub enum PlaceBase<'tcx> {
     /// local variable
     Local(Local),
@@ -1933,7 +1743,9 @@ pub struct Static<'tcx> {
     pub kind: StaticKind,
 }
 
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, RustcEncodable, RustcDecodable)]
+#[derive(
+    Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, RustcEncodable, RustcDecodable,
+)]
 pub enum StaticKind {
     Promoted(Promoted),
     Static(DefId),
@@ -1945,15 +1757,17 @@ impl_stable_hash_for!(struct Static<'tcx> {
 });
 
 /// The `Projection` data structure defines things of the form `base.x`, `*b` or `b[index]`.
-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord,
-         Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(
+    Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable,
+)]
 pub struct Projection<'tcx> {
     pub base: Place<'tcx>,
     pub elem: PlaceElem<'tcx>,
- }
+}
 
-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord,
-         Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(
+    Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable,
+)]
 pub enum ProjectionElem<V, T> {
     Deref,
     Field(Field, T),
@@ -2026,7 +1840,8 @@ impl<'tcx> Place<'tcx> {
     pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Place<'tcx> {
         self.elem(ProjectionElem::Downcast(
             Some(adt_def.variants[variant_index].ident.name),
-            variant_index))
+            variant_index,
+        ))
     }
 
     pub fn downcast_unnamed(self, variant_index: VariantIdx) -> Place<'tcx> {
@@ -2047,8 +1862,8 @@ impl<'tcx> Place<'tcx> {
     // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
     pub fn local_or_deref_local(&self) -> Option<Local> {
         match self {
-            Place::Base(PlaceBase::Local(local)) |
-            Place::Projection(box Projection {
+            Place::Base(PlaceBase::Local(local))
+            | Place::Projection(box Projection {
                 base: Place::Base(PlaceBase::Local(local)),
                 elem: ProjectionElem::Deref,
             }) => Some(*local),
@@ -2083,13 +1898,9 @@ impl<'tcx> Place<'tcx> {
         op: impl FnOnce(&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>) -> R,
     ) -> R {
         match self {
-            Place::Projection(interior) => interior.base.iterate2(
-                &Projections::List {
-                    projection: interior,
-                    next,
-                },
-                op,
-            ),
+            Place::Projection(interior) => {
+                interior.base.iterate2(&Projections::List { projection: interior, next }, op)
+            }
 
             Place::Base(base) => op(base, next.iter()),
         }
@@ -2119,10 +1930,7 @@ impl From<Local> for PlaceBase<'_> {
 pub enum Projections<'p, 'tcx> {
     Empty,
 
-    List {
-        projection: &'p Projection<'tcx>,
-        next: &'p Projections<'p, 'tcx>,
-    }
+    List { projection: &'p Projection<'tcx>, next: &'p Projections<'p, 'tcx> },
 }
 
 impl<'p, 'tcx> Projections<'p, 'tcx> {
@@ -2181,16 +1989,15 @@ impl<'tcx> Debug for Place<'tcx> {
             let projs_vec: Vec<_> = place_projections.collect();
             for projection in projs_vec.iter().rev() {
                 match projection.elem {
-                    ProjectionElem::Downcast(_, _) |
-                    ProjectionElem::Field(_, _) => {
+                    ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => {
                         write!(fmt, "(").unwrap();
                     }
                     ProjectionElem::Deref => {
                         write!(fmt, "(*").unwrap();
                     }
-                    ProjectionElem::Index(_) |
-                    ProjectionElem::ConstantIndex { .. } |
-                    ProjectionElem::Subslice { .. } => {}
+                    ProjectionElem::Index(_)
+                    | ProjectionElem::ConstantIndex { .. }
+                    | ProjectionElem::Subslice { .. } => {}
                 }
             }
         });
@@ -2215,18 +2022,10 @@ impl<'tcx> Debug for Place<'tcx> {
                     ProjectionElem::Index(ref index) => {
                         write!(fmt, "[{:?}]", index)?;
                     }
-                    ProjectionElem::ConstantIndex {
-                        offset,
-                        min_length,
-                        from_end: false,
-                    } => {
+                    ProjectionElem::ConstantIndex { offset, min_length, from_end: false } => {
                         write!(fmt, "[{:?} of {:?}]", offset, min_length)?;
                     }
-                    ProjectionElem::ConstantIndex {
-                        offset,
-                        min_length,
-                        from_end: true,
-                    } => {
+                    ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => {
                         write!(fmt, "[-{:?} of {:?}]", offset, min_length)?;
                     }
                     ProjectionElem::Subslice { from, to } if to == 0 => {
@@ -2251,21 +2050,11 @@ impl Debug for PlaceBase<'_> {
         match *self {
             PlaceBase::Local(id) => write!(fmt, "{:?}", id),
             PlaceBase::Static(box self::Static { ty, kind: StaticKind::Static(def_id) }) => {
-                write!(
-                    fmt,
-                    "({}: {:?})",
-                    ty::tls::with(|tcx| tcx.def_path_str(def_id)),
-                    ty
-                )
-            },
+                write!(fmt, "({}: {:?})", ty::tls::with(|tcx| tcx.def_path_str(def_id)), ty)
+            }
             PlaceBase::Static(box self::Static { ty, kind: StaticKind::Promoted(promoted) }) => {
-                write!(
-                    fmt,
-                    "({:?}: {:?})",
-                    promoted,
-                    ty
-                )
-            },
+                write!(fmt, "({:?}: {:?})", promoted, ty)
+            }
         }
     }
 }
@@ -2396,7 +2185,6 @@ pub enum Rvalue<'tcx> {
     Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
 }
 
-
 #[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
 pub enum CastKind {
     Misc,
@@ -2414,13 +2202,7 @@ pub enum AggregateKind<'tcx> {
     /// active field number and is present only for union expressions
     /// -- e.g., for a union expression `SomeUnion { c: .. }`, the
     /// active field index would identity the field `c`
-    Adt(
-        &'tcx AdtDef,
-        VariantIdx,
-        SubstsRef<'tcx>,
-        Option<UserTypeAnnotationIndex>,
-        Option<usize>,
-    ),
+    Adt(&'tcx AdtDef, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<usize>),
 
     Closure(DefId, ClosureSubsts<'tcx>),
     Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
@@ -2598,8 +2380,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
 
                     AggregateKind::Generator(def_id, _, _) => ty::tls::with(|tcx| {
                         if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) {
-                            let name = format!("[generator@{:?}]",
-                                               tcx.hir().span(hir_id));
+                            let name = format!("[generator@{:?}]", tcx.hir().span(hir_id));
                             let mut struct_fmt = fmt.debug_struct(&name);
 
                             if let Some(upvars) = tcx.upvars(def_id) {
@@ -2690,30 +2471,26 @@ impl<'tcx> UserTypeProjections {
         UserTypeProjections { contents: vec![] }
     }
 
-    pub fn from_projections(projs: impl Iterator<Item=(UserTypeProjection, Span)>) -> Self {
+    pub fn from_projections(projs: impl Iterator<Item = (UserTypeProjection, Span)>) -> Self {
         UserTypeProjections { contents: projs.collect() }
     }
 
-    pub fn projections_and_spans(&self) -> impl Iterator<Item=&(UserTypeProjection, Span)> {
+    pub fn projections_and_spans(&self) -> impl Iterator<Item = &(UserTypeProjection, Span)> {
         self.contents.iter()
     }
 
-    pub fn projections(&self) -> impl Iterator<Item=&UserTypeProjection> {
+    pub fn projections(&self) -> impl Iterator<Item = &UserTypeProjection> {
         self.contents.iter().map(|&(ref user_type, _span)| user_type)
     }
 
-    pub fn push_projection(
-        mut self,
-        user_ty: &UserTypeProjection,
-        span: Span,
-    ) -> Self {
+    pub fn push_projection(mut self, user_ty: &UserTypeProjection, span: Span) -> Self {
         self.contents.push((user_ty.clone(), span));
         self
     }
 
     fn map_projections(
         mut self,
-        mut f: impl FnMut(UserTypeProjection) -> UserTypeProjection
+        mut f: impl FnMut(UserTypeProjection) -> UserTypeProjection,
     ) -> Self {
         self.contents = self.contents.drain(..).map(|(proj, span)| (f(proj), span)).collect();
         self
@@ -2735,12 +2512,7 @@ impl<'tcx> UserTypeProjections {
         self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field))
     }
 
-    pub fn variant(
-        self,
-        adt_def: &'tcx AdtDef,
-        variant_index: VariantIdx,
-        field: Field,
-    ) -> Self {
+    pub fn variant(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx, field: Field) -> Self {
         self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field))
     }
 }
@@ -2766,7 +2538,7 @@ pub struct UserTypeProjection {
     pub projs: Vec<ProjectionKind>,
 }
 
-impl Copy for ProjectionKind { }
+impl Copy for ProjectionKind {}
 
 impl UserTypeProjection {
     pub(crate) fn index(mut self) -> Self {
@@ -2797,7 +2569,8 @@ impl UserTypeProjection {
     ) -> Self {
         self.projs.push(ProjectionElem::Downcast(
             Some(adt_def.variants[variant_index].ident.name),
-            variant_index));
+            variant_index,
+        ));
         self.projs.push(ProjectionElem::Field(field, ()));
         self
     }
@@ -2810,15 +2583,15 @@ impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
         use crate::mir::ProjectionElem::*;
 
         let base = self.base.fold_with(folder);
-        let projs: Vec<_> = self.projs
+        let projs: Vec<_> = self
+            .projs
             .iter()
-            .map(|elem| {
-                match elem {
-                    Deref => Deref,
-                    Field(f, ()) => Field(f.clone(), ()),
-                    Index(()) => Index(()),
-                    elem => elem.clone(),
-                }})
+            .map(|elem| match elem {
+                Deref => Deref,
+                Field(f, ()) => Field(f.clone(), ()),
+                Index(()) => Index(()),
+                elem => elem.clone(),
+            })
             .collect();
 
         UserTypeProjection { base, projs }
@@ -2911,20 +2684,14 @@ impl fmt::Debug for Location {
 }
 
 impl Location {
-    pub const START: Location = Location {
-        block: START_BLOCK,
-        statement_index: 0,
-    };
+    pub const START: Location = Location { block: START_BLOCK, statement_index: 0 };
 
     /// Returns the location immediately after this one within the enclosing block.
     ///
     /// Note that if this location represents a terminator, then the
     /// resulting location would be out of bounds and invalid.
     pub fn successor_within_block(&self) -> Location {
-        Location {
-            block: self.block,
-            statement_index: self.statement_index + 1,
-        }
+        Location { block: self.block, statement_index: self.statement_index + 1 }
     }
 
     /// Returns `true` if `other` is earlier in the control flow graph than `self`.
@@ -3114,8 +2881,19 @@ pub struct ClosureOutlivesRequirement<'tcx> {
 /// order of the category, thereby influencing diagnostic output.
 ///
 /// See also [rustc_mir::borrow_check::nll::constraints]
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord,
-         Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(
+    Copy,
+    Clone,
+    Debug,
+    Eq,
+    PartialEq,
+    PartialOrd,
+    Ord,
+    Hash,
+    RustcEncodable,
+    RustcDecodable,
+    HashStable,
+)]
 pub enum ConstraintCategory {
     Return,
     Yield,
@@ -3278,56 +3056,27 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
 
         let kind = match self.kind {
             Goto { target } => Goto { target },
-            SwitchInt {
-                ref discr,
-                switch_ty,
-                ref values,
-                ref targets,
-            } => SwitchInt {
+            SwitchInt { ref discr, switch_ty, ref values, ref targets } => SwitchInt {
                 discr: discr.fold_with(folder),
                 switch_ty: switch_ty.fold_with(folder),
                 values: values.clone(),
                 targets: targets.clone(),
             },
-            Drop {
-                ref location,
-                target,
-                unwind,
-            } => Drop {
-                location: location.fold_with(folder),
-                target,
-                unwind,
-            },
-            DropAndReplace {
-                ref location,
-                ref value,
-                target,
-                unwind,
-            } => DropAndReplace {
+            Drop { ref location, target, unwind } => {
+                Drop { location: location.fold_with(folder), target, unwind }
+            }
+            DropAndReplace { ref location, ref value, target, unwind } => DropAndReplace {
                 location: location.fold_with(folder),
                 value: value.fold_with(folder),
                 target,
                 unwind,
             },
-            Yield {
-                ref value,
-                resume,
-                drop,
-            } => Yield {
-                value: value.fold_with(folder),
-                resume: resume,
-                drop: drop,
-            },
-            Call {
-                ref func,
-                ref args,
-                ref destination,
-                cleanup,
-                from_hir_call,
-            } => {
-                let dest = destination
-                    .as_ref()
-                    .map(|&(ref loc, dest)| (loc.fold_with(folder), dest));
+            Yield { ref value, resume, drop } => {
+                Yield { value: value.fold_with(folder), resume: resume, drop: drop }
+            }
+            Call { ref func, ref args, ref destination, cleanup, from_hir_call } => {
+                let dest =
+                    destination.as_ref().map(|&(ref loc, dest)| (loc.fold_with(folder), dest));
 
                 Call {
                     func: func.fold_with(folder),
@@ -3337,13 +3086,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
                     from_hir_call,
                 }
             }
-            Assert {
-                ref cond,
-                expected,
-                ref msg,
-                target,
-                cleanup,
-            } => {
+            Assert { ref cond, expected, ref msg, target, cleanup } => {
                 let msg = if let InterpError::BoundsCheck { ref len, ref index } = *msg {
                     InterpError::BoundsCheck {
                         len: len.fold_with(folder),
@@ -3352,62 +3095,34 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
                 } else {
                     msg.clone()
                 };
-                Assert {
-                    cond: cond.fold_with(folder),
-                    expected,
-                    msg,
-                    target,
-                    cleanup,
-                }
+                Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup }
             }
             GeneratorDrop => GeneratorDrop,
             Resume => Resume,
             Abort => Abort,
             Return => Return,
             Unreachable => Unreachable,
-            FalseEdges {
-                real_target,
-                imaginary_target,
-            } => FalseEdges {
-                real_target,
-                imaginary_target,
-            },
-            FalseUnwind {
-                real_target,
-                unwind,
-            } => FalseUnwind {
-                real_target,
-                unwind,
-            },
+            FalseEdges { real_target, imaginary_target } => {
+                FalseEdges { real_target, imaginary_target }
+            }
+            FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
         };
-        Terminator {
-            source_info: self.source_info,
-            kind,
-        }
+        Terminator { source_info: self.source_info, kind }
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
         use crate::mir::TerminatorKind::*;
 
         match self.kind {
-            SwitchInt {
-                ref discr,
-                switch_ty,
-                ..
-            } => discr.visit_with(visitor) || switch_ty.visit_with(visitor),
+            SwitchInt { ref discr, switch_ty, .. } => {
+                discr.visit_with(visitor) || switch_ty.visit_with(visitor)
+            }
             Drop { ref location, .. } => location.visit_with(visitor),
-            DropAndReplace {
-                ref location,
-                ref value,
-                ..
-            } => location.visit_with(visitor) || value.visit_with(visitor),
+            DropAndReplace { ref location, ref value, .. } => {
+                location.visit_with(visitor) || value.visit_with(visitor)
+            }
             Yield { ref value, .. } => value.visit_with(visitor),
-            Call {
-                ref func,
-                ref args,
-                ref destination,
-                ..
-            } => {
+            Call { ref func, ref args, ref destination, .. } => {
                 let dest = if let Some((ref loc, _)) = *destination {
                     loc.visit_with(visitor)
                 } else {
@@ -3415,9 +3130,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
                 };
                 dest || func.visit_with(visitor) || args.visit_with(visitor)
             }
-            Assert {
-                ref cond, ref msg, ..
-            } => {
+            Assert { ref cond, ref msg, .. } => {
                 if cond.visit_with(visitor) {
                     if let InterpError::BoundsCheck { ref len, ref index } = *msg {
                         len.visit_with(visitor) || index.visit_with(visitor)
@@ -3564,11 +3277,12 @@ impl<'tcx> TypeFoldable<'tcx> for Projection<'tcx> {
     fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool {
         use crate::mir::ProjectionElem::*;
 
-        self.base.visit_with(visitor) || match self.elem {
-            Field(_, ref ty) => ty.visit_with(visitor),
-            Index(ref v) => v.visit_with(visitor),
-            _ => false,
-        }
+        self.base.visit_with(visitor)
+            || match self.elem {
+                Field(_, ref ty) => ty.visit_with(visitor),
+                Index(ref v) => v.visit_with(visitor),
+                _ => false,
+            }
     }
 }
 
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index 695bf1f077c..2adbd03b24f 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -15,7 +15,7 @@ either = "1.5.0"
 dot = { path = "../libgraphviz", package = "graphviz" }
 log = "0.4"
 log_settings = "0.1.1"
-polonius-engine = "0.7.0"
+polonius-engine  = "0.9.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 9a9310fbe05..bb217a1f965 100644
--- a/src/librustc_mir/borrow_check/flows.rs
+++ b/src/librustc_mir/borrow_check/flows.rs
@@ -3,7 +3,7 @@
 //! FIXME: this might be better as a "generic" fixed-point combinator,
 //! but is not as ugly as it is right now.
 
-use rustc::mir::{BasicBlock, Location};
+use rustc::mir::{BasicBlock, Local, Location};
 use rustc::ty::RegionVid;
 use rustc_data_structures::bit_set::BitIter;
 
@@ -15,12 +15,14 @@ use crate::dataflow::indexes::BorrowIndex;
 use crate::dataflow::move_paths::HasMoveData;
 use crate::dataflow::Borrows;
 use crate::dataflow::EverInitializedPlaces;
-use crate::dataflow::{FlowAtLocation, FlowsAtLocation};
 use crate::dataflow::MaybeUninitializedPlaces;
+use crate::dataflow::{FlowAtLocation, FlowsAtLocation};
 use either::Either;
 use std::fmt;
 use std::rc::Rc;
 
+crate type PoloniusOutput = Output<RegionVid, BorrowIndex, LocationIndex, Local>;
+
 // (forced to be `pub` due to its use as an associated type below.)
 crate struct Flows<'b, 'tcx> {
     borrows: FlowAtLocation<'tcx, Borrows<'b, 'tcx>>,
@@ -28,7 +30,7 @@ crate struct Flows<'b, 'tcx> {
     pub ever_inits: FlowAtLocation<'tcx, EverInitializedPlaces<'b, 'tcx>>,
 
     /// Polonius Output
-    pub polonius_output: Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
+    pub polonius_output: Option<Rc<PoloniusOutput>>,
 }
 
 impl<'b, 'tcx> Flows<'b, 'tcx> {
@@ -36,14 +38,9 @@ impl<'b, 'tcx> Flows<'b, 'tcx> {
         borrows: FlowAtLocation<'tcx, Borrows<'b, 'tcx>>,
         uninits: FlowAtLocation<'tcx, MaybeUninitializedPlaces<'b, 'tcx>>,
         ever_inits: FlowAtLocation<'tcx, EverInitializedPlaces<'b, 'tcx>>,
-        polonius_output: Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
+        polonius_output: Option<Rc<PoloniusOutput>>,
     ) -> Self {
-        Flows {
-            borrows,
-            uninits,
-            ever_inits,
-            polonius_output,
-        }
+        Flows { borrows, uninits, ever_inits, polonius_output }
     }
 
     crate fn borrows_in_scope(
diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs
index d84afeac185..05451cdfb83 100644
--- a/src/librustc_mir/borrow_check/nll/facts.rs
+++ b/src/librustc_mir/borrow_check/nll/facts.rs
@@ -2,6 +2,7 @@ use crate::borrow_check::location::{LocationIndex, LocationTable};
 use crate::dataflow::indexes::BorrowIndex;
 use polonius_engine::AllFacts as PoloniusAllFacts;
 use polonius_engine::Atom;
+use rustc::mir::Local;
 use rustc::ty::{RegionVid, TyCtxt};
 use rustc_data_structures::indexed_vec::Idx;
 use std::error::Error;
@@ -10,7 +11,7 @@ use std::fs::{self, File};
 use std::io::Write;
 use std::path::Path;
 
-crate type AllFacts = PoloniusAllFacts<RegionVid, BorrowIndex, LocationIndex>;
+crate type AllFacts = PoloniusAllFacts<RegionVid, BorrowIndex, LocationIndex, Local>;
 
 crate trait AllFactsExt {
     /// Returns `true` if there is a need to gather `AllFacts` given the
@@ -27,8 +28,7 @@ crate trait AllFactsExt {
 impl AllFactsExt for AllFacts {
     /// Return
     fn enabled(tcx: TyCtxt<'_>) -> bool {
-        tcx.sess.opts.debugging_opts.nll_facts
-            || tcx.sess.opts.debugging_opts.polonius
+        tcx.sess.opts.debugging_opts.nll_facts || tcx.sess.opts.debugging_opts.polonius
     }
 
     fn write_to_dir(
@@ -60,6 +60,12 @@ impl AllFactsExt for AllFacts {
                 outlives,
                 region_live_at,
                 invalidates,
+                var_used,
+                var_defined,
+                var_drop_used,
+                var_uses_region,
+                var_drops_region,
+                var_initialized_on_exit,
             ])
         }
         Ok(())
@@ -84,11 +90,7 @@ struct FactWriter<'w> {
 }
 
 impl<'w> FactWriter<'w> {
-    fn write_facts_to_path<T>(
-        &self,
-        rows: &[T],
-        file_name: &str,
-    ) -> Result<(), Box<dyn Error>>
+    fn write_facts_to_path<T>(&self, rows: &[T], file_name: &str) -> Result<(), Box<dyn Error>>
     where
         T: FactRow,
     {
@@ -102,19 +104,11 @@ impl<'w> FactWriter<'w> {
 }
 
 trait FactRow {
-    fn write(
-        &self,
-        out: &mut File,
-        location_table: &LocationTable,
-    ) -> Result<(), Box<dyn Error>>;
+    fn write(&self, out: &mut File, location_table: &LocationTable) -> Result<(), Box<dyn Error>>;
 }
 
 impl FactRow for RegionVid {
-    fn write(
-        &self,
-        out: &mut File,
-        location_table: &LocationTable,
-    ) -> Result<(), Box<dyn Error>> {
+    fn write(&self, out: &mut File, location_table: &LocationTable) -> Result<(), Box<dyn Error>> {
         write_row(out, location_table, &[self])
     }
 }
@@ -124,11 +118,7 @@ where
     A: FactCell,
     B: FactCell,
 {
-    fn write(
-        &self,
-        out: &mut File,
-        location_table: &LocationTable,
-    ) -> Result<(), Box<dyn Error>> {
+    fn write(&self, out: &mut File, location_table: &LocationTable) -> Result<(), Box<dyn Error>> {
         write_row(out, location_table, &[&self.0, &self.1])
     }
 }
@@ -139,11 +129,7 @@ where
     B: FactCell,
     C: FactCell,
 {
-    fn write(
-        &self,
-        out: &mut File,
-        location_table: &LocationTable,
-    ) -> Result<(), Box<dyn Error>> {
+    fn write(&self, out: &mut File, location_table: &LocationTable) -> Result<(), Box<dyn Error>> {
         write_row(out, location_table, &[&self.0, &self.1, &self.2])
     }
 }
@@ -155,11 +141,7 @@ where
     C: FactCell,
     D: FactCell,
 {
-    fn write(
-        &self,
-        out: &mut File,
-        location_table: &LocationTable,
-    ) -> Result<(), Box<dyn Error>> {
+    fn write(&self, out: &mut File, location_table: &LocationTable) -> Result<(), Box<dyn Error>> {
         write_row(out, location_table, &[&self.0, &self.1, &self.2, &self.3])
     }
 }
@@ -170,11 +152,7 @@ fn write_row(
     columns: &[&dyn FactCell],
 ) -> Result<(), Box<dyn Error>> {
     for (index, c) in columns.iter().enumerate() {
-        let tail = if index == columns.len() - 1 {
-            "\n"
-        } else {
-            "\t"
-        };
+        let tail = if index == columns.len() - 1 { "\n" } else { "\t" };
         write!(out, "{:?}{}", c.to_string(location_table), tail)?;
     }
     Ok(())
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index eb63e0de195..a2c5ad202e8 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -11,7 +11,7 @@ use crate::transform::MirSource;
 use crate::borrow_check::Upvar;
 use rustc::hir::def_id::DefId;
 use rustc::infer::InferCtxt;
-use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Body};
+use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Body};
 use rustc::ty::{self, RegionKind, RegionVid};
 use rustc_errors::Diagnostic;
 use std::fmt::Debug;
@@ -84,7 +84,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
     errors_buffer: &mut Vec<Diagnostic>,
 ) -> (
     RegionInferenceContext<'tcx>,
-    Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
+    Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex, Local>>>,
     Option<ClosureRegionRequirements<'tcx>>,
 ) {
     let mut all_facts = if AllFacts::enabled(infcx.tcx) {
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
index 4af78fa5e0f..8970009b6ee 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
@@ -7,7 +7,7 @@ use crate::borrow_check::nll::ToRegionVid;
 use crate::dataflow::move_paths::MoveData;
 use crate::dataflow::FlowAtLocation;
 use crate::dataflow::MaybeInitializedPlaces;
-use rustc::mir::{Local, Body};
+use rustc::mir::{Body, Local};
 use rustc::ty::{RegionVid, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
 use std::rc::Rc;
@@ -15,6 +15,7 @@ use std::rc::Rc;
 use super::TypeChecker;
 
 mod local_use_map;
+mod polonius;
 mod trace;
 
 /// Combines liveness analysis with initialization analysis to
@@ -57,15 +58,9 @@ pub(super) fn generate<'tcx>(
     };
 
     if !live_locals.is_empty() {
-        trace::trace(
-            typeck,
-            body,
-            elements,
-            flow_inits,
-            move_data,
-            live_locals,
-            location_table,
-        );
+        trace::trace(typeck, body, elements, flow_inits, move_data, live_locals, location_table);
+
+        polonius::populate_var_liveness_facts(typeck, body, location_table);
     }
 }
 
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs
new file mode 100644
index 00000000000..20d7ec55e3e
--- /dev/null
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs
@@ -0,0 +1,94 @@
+use crate::borrow_check::location::{LocationIndex, LocationTable};
+use crate::util::liveness::{categorize, DefUse};
+use rustc::mir::visit::{PlaceContext, Visitor};
+use rustc::mir::{Body, Local, Location};
+use rustc::ty::subst::Kind;
+use rustc::ty::Ty;
+
+use super::TypeChecker;
+
+type VarPointRelations = Vec<(Local, LocationIndex)>;
+
+struct LivenessPointFactsExtractor<'me> {
+    var_defined: &'me mut VarPointRelations,
+    var_used: &'me mut VarPointRelations,
+    location_table: &'me LocationTable,
+}
+
+// A Visitor to walk through the MIR and extract point-wise facts
+impl LivenessPointFactsExtractor<'_> {
+    fn location_to_index(&self, location: Location) -> LocationIndex {
+        self.location_table.mid_index(location)
+    }
+
+    fn insert_def(&mut self, local: Local, location: Location) {
+        debug!("LivenessFactsExtractor::insert_def()");
+        self.var_defined.push((local, self.location_to_index(location)));
+    }
+
+    fn insert_use(&mut self, local: Local, location: Location) {
+        debug!("LivenessFactsExtractor::insert_use()");
+        self.var_used.push((local, self.location_to_index(location)));
+    }
+}
+
+impl Visitor<'tcx> for LivenessPointFactsExtractor<'_> {
+    fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
+        match categorize(context) {
+            Some(DefUse::Def) => self.insert_def(local, location),
+            Some(DefUse::Use) => self.insert_use(local, location),
+            _ => (),
+            // NOTE: Drop handling is now done in trace()
+        }
+    }
+}
+
+fn add_var_uses_regions(typeck: &mut TypeChecker<'_, 'tcx>, local: Local, ty: Ty<'tcx>) {
+    debug!("add_regions(local={:?}, type={:?})", local, ty);
+    typeck.tcx().for_each_free_region(&ty, |region| {
+        let region_vid = typeck.borrowck_context.universal_regions.to_region_vid(region);
+        debug!("add_regions for region {:?}", region_vid);
+        if let Some(facts) = typeck.borrowck_context.all_facts {
+            facts.var_uses_region.push((local, region_vid));
+        }
+    });
+}
+
+pub(super) fn populate_var_liveness_facts(
+    typeck: &mut TypeChecker<'_, 'tcx>,
+    mir: &Body<'tcx>,
+    location_table: &LocationTable,
+) {
+    debug!("populate_var_liveness_facts()");
+
+    if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
+        LivenessPointFactsExtractor {
+            var_defined: &mut facts.var_defined,
+            var_used: &mut facts.var_used,
+            location_table,
+        }
+        .visit_body(mir);
+    }
+
+    for (local, local_decl) in mir.local_decls.iter_enumerated() {
+        add_var_uses_regions(typeck, local, local_decl.ty);
+    }
+}
+
+// For every potentially drop()-touched region `region` in `local`'s type
+// (`kind`), emit a Polonius `var_drops_region(local, region)` fact.
+pub(super) fn add_var_drops_regions(
+    typeck: &mut TypeChecker<'_, 'tcx>,
+    local: Local,
+    kind: &Kind<'tcx>,
+) {
+    debug!("add_var_drops_region(local={:?}, kind={:?}", local, kind);
+    let tcx = typeck.tcx();
+
+    tcx.for_each_free_region(kind, |drop_live_region| {
+        let region_vid = typeck.borrowck_context.universal_regions.to_region_vid(drop_live_region);
+        if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
+            facts.var_drops_region.push((local, region_vid));
+        };
+    });
+}
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
index f160f658f55..039ed939ada 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
@@ -1,13 +1,14 @@
 use crate::borrow_check::location::LocationTable;
 use crate::borrow_check::nll::region_infer::values::{self, PointIndex, RegionValueElements};
 use crate::borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap;
+use crate::borrow_check::nll::type_check::liveness::polonius;
 use crate::borrow_check::nll::type_check::NormalizeLocation;
 use crate::borrow_check::nll::type_check::TypeChecker;
 use crate::dataflow::indexes::MovePathIndex;
 use crate::dataflow::move_paths::MoveData;
 use crate::dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces};
 use rustc::infer::canonical::QueryRegionConstraints;
-use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, Body};
+use rustc::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
 use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
 use rustc::traits::query::type_op::outlives::DropckOutlives;
 use rustc::traits::query::type_op::TypeOp;
@@ -130,6 +131,12 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
         for local in live_locals {
             self.reset_local_state();
             self.add_defs_for(local);
+
+            // FIXME: this is temporary until we can generate our own initialization
+            if self.cx.typeck.borrowck_context.all_facts.is_some() {
+                self.add_polonius_var_initialized_on_exit_for(local)
+            }
+
             self.compute_use_live_points_for(local);
             self.compute_drop_live_points_for(local);
 
@@ -150,6 +157,63 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
         }
     }
 
+    // WARNING: panics if self.cx.typeck.borrowck_context.all_facts != None
+    //
+    // FIXME: this analysis (the initialization tracking) should be
+    // done in Polonius, but isn't yet.
+    fn add_polonius_var_initialized_on_exit_for(&mut self, local: Local) {
+        let move_path = self.cx.move_data.rev_lookup.find_local(local);
+        let facts = self.cx.typeck.borrowck_context.all_facts.as_mut().unwrap();
+        for block in self.cx.body.basic_blocks().indices() {
+            debug!("polonius: generating initialization facts for {:?} in {:?}", local, block);
+
+            // iterate through the block, applying the effects of each statement
+            // up to and including location, and populate `var_initialized_on_exit`
+            self.cx.flow_inits.reset_to_entry_of(block);
+            let start_location = Location { block, statement_index: 0 };
+            self.cx.flow_inits.apply_local_effect(start_location);
+
+            for statement_index in 0..self.cx.body[block].statements.len() {
+                let current_location = Location { block, statement_index };
+
+                self.cx.flow_inits.reconstruct_statement_effect(current_location);
+
+                // statement has not yet taken effect:
+                if self.cx.flow_inits.has_any_child_of(move_path).is_some() {
+                    facts
+                        .var_initialized_on_exit
+                        .push((local, self.cx.location_table.start_index(current_location)));
+                }
+
+                // statement has now taken effect
+                self.cx.flow_inits.apply_local_effect(current_location);
+
+                if self.cx.flow_inits.has_any_child_of(move_path).is_some() {
+                    facts
+                        .var_initialized_on_exit
+                        .push((local, self.cx.location_table.mid_index(current_location)));
+                }
+            }
+
+            let terminator_location = self.cx.body.terminator_loc(block);
+
+            if self.cx.flow_inits.has_any_child_of(move_path).is_some() {
+                facts
+                    .var_initialized_on_exit
+                    .push((local, self.cx.location_table.start_index(terminator_location)));
+            }
+
+            // apply the effects of the terminator and push it if needed
+            self.cx.flow_inits.reset_to_exit_of(block);
+
+            if self.cx.flow_inits.has_any_child_of(move_path).is_some() {
+                facts
+                    .var_initialized_on_exit
+                    .push((local, self.cx.location_table.mid_index(terminator_location)));
+            }
+        }
+    }
+
     /// Clear the value of fields that are "per local variable".
     fn reset_local_state(&mut self) {
         self.defs.clear();
@@ -183,9 +247,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
             }
 
             if self.use_live_at.insert(p) {
-                self.cx
-                    .elements
-                    .push_predecessors(self.cx.body, p, &mut self.stack)
+                self.cx.elements.push_predecessors(self.cx.body, p, &mut self.stack)
             }
         }
     }
@@ -211,6 +273,11 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
             debug_assert_eq!(self.cx.body.terminator_loc(location.block), location,);
 
             if self.cx.initialized_at_terminator(location.block, mpi) {
+                // FIXME: this analysis (the initialization tracking) should be
+                // done in Polonius, but isn't yet.
+                if let Some(facts) = self.cx.typeck.borrowck_context.all_facts {
+                    facts.var_drop_used.push((local, self.cx.location_table.mid_index(location)));
+                }
                 if self.drop_live_at.insert(drop_point) {
                     self.drop_locations.push(location);
                     self.stack.push(drop_point);
@@ -218,10 +285,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
             }
         }
 
-        debug!(
-            "compute_drop_live_points_for: drop_locations={:?}",
-            self.drop_locations
-        );
+        debug!("compute_drop_live_points_for: drop_locations={:?}", self.drop_locations);
 
         // Reverse DFS. But for drops, we do it a bit differently.
         // The stack only ever stores *terminators of blocks*. Within
@@ -257,17 +321,11 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
         // block.  One of them may be either a definition or use
         // live point.
         let term_location = self.cx.elements.to_location(term_point);
-        debug_assert_eq!(
-            self.cx.body.terminator_loc(term_location.block),
-            term_location,
-        );
+        debug_assert_eq!(self.cx.body.terminator_loc(term_location.block), term_location,);
         let block = term_location.block;
         let entry_point = self.cx.elements.entry_point(term_location.block);
         for p in (entry_point..term_point).rev() {
-            debug!(
-                "compute_drop_live_points_for_block: p = {:?}",
-                self.cx.elements.to_location(p),
-            );
+            debug!("compute_drop_live_points_for_block: p = {:?}", self.cx.elements.to_location(p));
 
             if self.defs.contains(p) {
                 debug!("compute_drop_live_points_for_block: def site");
@@ -286,10 +344,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
         }
 
         for &pred_block in self.cx.body.predecessors_for(block).iter() {
-            debug!(
-                "compute_drop_live_points_for_block: pred_block = {:?}",
-                pred_block,
-            );
+            debug!("compute_drop_live_points_for_block: pred_block = {:?}", pred_block,);
 
             // Check whether the variable is (at least partially)
             // initialized at the exit of this predecessor. If so, we
@@ -320,18 +375,12 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
             // If the terminator of this predecessor either *assigns*
             // our value or is a "normal use", then stop.
             if self.defs.contains(pred_term_point) {
-                debug!(
-                    "compute_drop_live_points_for_block: defined at {:?}",
-                    pred_term_loc
-                );
+                debug!("compute_drop_live_points_for_block: defined at {:?}", pred_term_loc);
                 continue;
             }
 
             if self.use_live_at.contains(pred_term_point) {
-                debug!(
-                    "compute_drop_live_points_for_block: use-live at {:?}",
-                    pred_term_loc
-                );
+                debug!("compute_drop_live_points_for_block: use-live at {:?}", pred_term_loc);
                 continue;
             }
 
@@ -392,10 +441,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
         // "just ahead" of a terminator.
         self.flow_inits.reset_to_entry_of(block);
         for statement_index in 0..self.body[block].statements.len() {
-            let location = Location {
-                block,
-                statement_index,
-            };
+            let location = Location { block, statement_index };
             self.flow_inits.reconstruct_statement_effect(location);
             self.flow_inits.apply_local_effect(location);
         }
@@ -462,12 +508,11 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
 
         if let Some(data) = &drop_data.region_constraint_data {
             for &drop_location in drop_locations {
-                self.typeck
-                    .push_region_constraints(
-                        drop_location.to_locations(),
-                        ConstraintCategory::Boring,
-                        data,
-                    );
+                self.typeck.push_region_constraints(
+                    drop_location.to_locations(),
+                    ConstraintCategory::Boring,
+                    data,
+                );
             }
         }
 
@@ -487,6 +532,8 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
                 live_at,
                 self.location_table,
             );
+
+            polonius::add_var_drops_regions(&mut self.typeck, dropped_local, &kind);
         }
     }
 
@@ -505,14 +552,15 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
 
         let tcx = typeck.tcx();
         tcx.for_each_free_region(&value, |live_region| {
-            let live_region_vid = typeck.borrowck_context
-                .universal_regions
-                .to_region_vid(live_region);
-            typeck.borrowck_context
+            let live_region_vid =
+                typeck.borrowck_context.universal_regions.to_region_vid(live_region);
+            typeck
+                .borrowck_context
                 .constraints
                 .liveness_constraints
                 .add_elements(live_region_vid, live_at);
 
+            // FIXME: remove this when we can generate our own region-live-at reliably
             if let Some(facts) = typeck.borrowck_context.all_facts {
                 for point in live_at.iter() {
                     let loc = elements.to_location(point);
@@ -530,14 +578,9 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
         debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
 
         let param_env = typeck.param_env;
-        let (dropck_result, region_constraint_data) = param_env
-            .and(DropckOutlives::new(dropped_ty))
-            .fully_perform(typeck.infcx)
-            .unwrap();
-
-        DropData {
-            dropck_result,
-            region_constraint_data,
-        }
+        let (dropck_result, region_constraint_data) =
+            param_env.and(DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx).unwrap();
+
+        DropData { dropck_result, region_constraint_data }
     }
 }