From 08a60ac6ed68628c4ccdb3fcbb6d780cadd7565a Mon Sep 17 00:00:00 2001
From: Matthew Jasper <mjjasper1@gmail.com>
Date: Sat, 21 Sep 2019 16:32:24 +0100
Subject: [PATCH 1/2] Calculate liveness for the same locals with and without
 -Zpolonius

This fixes some test differences and also avoids overflow in
issue-38591.rs.
---
 .../nll/type_check/liveness/local_use_map.rs  |   4 +
 .../nll/type_check/liveness/mod.rs            |  52 +++---
 .../nll/type_check/liveness/polonius.rs       |  11 +-
 .../nll/type_check/liveness/trace.rs          |  37 ++++-
 ...wck-escaping-closure-error.polonius.stderr |  16 --
 ...k-escaping-closure-error-2.polonius.stderr |  16 --
 ...ref-mut-in-let-issue-46557.polonius.stderr |  59 -------
 ...al-binding-from-desugaring.polonius.stderr |  16 --
 ...phase-surprise-no-conflict.polonius.stderr | 148 ------------------
 .../consts/promote_const_let.polonius.stderr  |  29 ----
 ...dropck_trait_cycle_checked.polonius.stderr |  78 ---------
 ...escapes-but-not-over-yield.polonius.stderr |  20 ---
 src/test/ui/nll/get_default.polonius.stderr   |   5 +-
 .../loan_ends_mid_block_pair.polonius.stderr  |  15 --
 .../nll/polonius/polonius-smoke-test.stderr   |   4 +-
 ...return-ref-mut-issue-46557.polonius.stderr |  15 --
 ...ures-failed-recursive-fn-1.polonius.stderr |  60 -------
 17 files changed, 84 insertions(+), 501 deletions(-)
 delete mode 100644 src/test/ui/async-await/async-borrowck-escaping-closure-error.polonius.stderr
 delete mode 100644 src/test/ui/borrowck/borrowck-escaping-closure-error-2.polonius.stderr
 delete mode 100644 src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.polonius.stderr
 delete mode 100644 src/test/ui/borrowck/return-local-binding-from-desugaring.polonius.stderr
 delete mode 100644 src/test/ui/borrowck/two-phase-surprise-no-conflict.polonius.stderr
 delete mode 100644 src/test/ui/consts/promote_const_let.polonius.stderr
 delete mode 100644 src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr
 delete mode 100644 src/test/ui/generator/ref-escapes-but-not-over-yield.polonius.stderr
 delete mode 100644 src/test/ui/nll/loan_ends_mid_block_pair.polonius.stderr
 delete mode 100644 src/test/ui/nll/return-ref-mut-issue-46557.polonius.stderr
 delete mode 100644 src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.polonius.stderr

diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
index 7689ece7066..7dee00b3eca 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
@@ -70,6 +70,10 @@ impl LocalUseMap {
             appearances: IndexVec::new(),
         };
 
+        if live_locals.is_empty() {
+            return local_use_map;
+        }
+
         let mut locals_with_use_data: IndexVec<Local, bool> =
             IndexVec::from_elem_n(false, body.local_decls.len());
         live_locals.iter().for_each(|&local| locals_with_use_data[local] = true);
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 3f2ec1ba970..a01b528833b 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
@@ -36,31 +36,39 @@ pub(super) fn generate<'tcx>(
 ) {
     debug!("liveness::generate");
 
-    let live_locals: Vec<Local> = if AllFacts::enabled(typeck.tcx()) {
-        // If "dump facts from NLL analysis" was requested perform
-        // the liveness analysis for all `Local`s. This case opens
-        // the possibility of the variables being analyzed in `trace`
-        // to be *any* `Local`, not just the "live" ones, so we can't
-        // make any assumptions past this point as to the characteristics
-        // of the `live_locals`.
-        // FIXME: Review "live" terminology past this point, we should
-        // not be naming the `Local`s as live.
-        body.local_decls.indices().collect()
+    let free_regions = regions_that_outlive_free_regions(
+        typeck.infcx.num_region_vars(),
+        &typeck.borrowck_context.universal_regions,
+        &typeck.borrowck_context.constraints.outlives_constraints,
+    );
+    let live_locals = compute_live_locals(typeck.tcx(), &free_regions, body);
+    let facts_enabled = AllFacts::enabled(typeck.tcx());
+
+
+    let polonius_drop_used = if facts_enabled {
+        let mut drop_used = Vec::new();
+        polonius::populate_access_facts(
+            typeck,
+            body,
+            location_table,
+            move_data,
+            &mut drop_used,
+        );
+        Some(drop_used)
     } else {
-        let free_regions = {
-            regions_that_outlive_free_regions(
-                typeck.infcx.num_region_vars(),
-                &typeck.borrowck_context.universal_regions,
-                &typeck.borrowck_context.constraints.outlives_constraints,
-            )
-        };
-        compute_live_locals(typeck.tcx(), &free_regions, body)
+        None
     };
 
-    if !live_locals.is_empty() {
-        trace::trace(typeck, body, elements, flow_inits, move_data, live_locals);
-
-        polonius::populate_access_facts(typeck, body, location_table, move_data);
+    if !live_locals.is_empty() || facts_enabled {
+        trace::trace(
+            typeck,
+            body,
+            elements,
+            flow_inits,
+            move_data,
+            live_locals,
+            polonius_drop_used,
+        );
     }
 }
 
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
index e37ddbda4be..526ad7fb905 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs
@@ -16,7 +16,7 @@ struct UseFactsExtractor<'me> {
     var_defined: &'me mut VarPointRelations,
     var_used: &'me mut VarPointRelations,
     location_table: &'me LocationTable,
-    var_drop_used: &'me mut VarPointRelations,
+    var_drop_used: &'me mut Vec<(Local, Location)>,
     move_data: &'me MoveData<'me>,
     path_accessed_at: &'me mut MovePathPointRelations,
 }
@@ -39,7 +39,7 @@ impl UseFactsExtractor<'_> {
 
     fn insert_drop_use(&mut self, local: Local, location: Location) {
         debug!("LivenessFactsExtractor::insert_drop_use()");
-        self.var_drop_used.push((local, self.location_to_index(location)));
+        self.var_drop_used.push((local, location));
     }
 
     fn insert_path_access(&mut self, path: MovePathIndex, location: Location) {
@@ -100,6 +100,7 @@ pub(super) fn populate_access_facts(
     body: &Body<'tcx>,
     location_table: &LocationTable,
     move_data: &MoveData<'_>,
+    drop_used: &mut Vec<(Local, Location)>,
 ) {
     debug!("populate_var_liveness_facts()");
 
@@ -107,12 +108,16 @@ pub(super) fn populate_access_facts(
         UseFactsExtractor {
             var_defined: &mut facts.var_defined,
             var_used: &mut facts.var_used,
-            var_drop_used: &mut facts.var_drop_used,
+            var_drop_used: drop_used,
             path_accessed_at: &mut facts.path_accessed_at,
             location_table,
             move_data,
         }
         .visit_body(body);
+
+        facts.var_drop_used.extend(drop_used.iter().map(|&(local, location)| {
+            (local, location_table.mid_index(location))
+        }));
     }
 
     for (local, local_decl) in body.local_decls.iter_enumerated() {
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 36482a7b135..eacc4d084db 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
@@ -13,7 +13,7 @@ use rustc::traits::query::type_op::outlives::DropckOutlives;
 use rustc::traits::query::type_op::TypeOp;
 use rustc::ty::{Ty, TypeFoldable};
 use rustc_index::bit_set::HybridBitSet;
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use std::rc::Rc;
 
 /// This is the heart of the liveness computation. For each variable X
@@ -37,6 +37,7 @@ pub(super) fn trace(
     flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>,
     move_data: &MoveData<'tcx>,
     live_locals: Vec<Local>,
+    polonius_drop_used: Option<Vec<(Local, Location)>>,
 ) {
     debug!("trace()");
 
@@ -52,7 +53,13 @@ pub(super) fn trace(
         drop_data: FxHashMap::default(),
     };
 
-    LivenessResults::new(cx).compute_for_all_locals(live_locals);
+    let mut results = LivenessResults::new(cx);
+
+    if let Some(drop_used) = polonius_drop_used {
+        results.add_extra_drop_facts(drop_used, live_locals.iter().copied().collect())
+    }
+
+    results.compute_for_all_locals(live_locals);
 }
 
 /// Contextual state for the type-liveness generator.
@@ -145,6 +152,32 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
         }
     }
 
+    /// Add extra drop facts needed for Polonius.
+    ///
+    /// Add facts for all locals with free regions, since regions may outlive
+    /// the function body only at certain nodes in the CFG.
+    fn add_extra_drop_facts(
+        &mut self,
+        drop_used: Vec<(Local, Location)>,
+        live_locals: FxHashSet<Local>,
+    ) {
+        let locations = HybridBitSet::new_empty(self.cx.elements.num_points());
+
+        for (local, location) in drop_used {
+            if !live_locals.contains(&local) {
+                let local_ty = self.cx.body.local_decls[local].ty;
+                if local_ty.has_free_regions() {
+                    self.cx.add_drop_live_facts_for(
+                        local,
+                        local_ty,
+                        &[location],
+                        &locations,
+                    );
+                }
+            }
+        }
+    }
+
     /// Clear the value of fields that are "per local variable".
     fn reset_local_state(&mut self) {
         self.defs.clear();
diff --git a/src/test/ui/async-await/async-borrowck-escaping-closure-error.polonius.stderr b/src/test/ui/async-await/async-borrowck-escaping-closure-error.polonius.stderr
deleted file mode 100644
index 5f20367b6ab..00000000000
--- a/src/test/ui/async-await/async-borrowck-escaping-closure-error.polonius.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0597]: `x` does not live long enough
-  --> $DIR/async-borrowck-escaping-closure-error.rs:5:24
-   |
-LL |     Box::new((async || x)())
-   |     -------------------^----
-   |     |         |        |
-   |     |         |        borrowed value does not live long enough
-   |     |         value captured here
-   |     borrow later used here
-LL |
-LL | }
-   | - `x` dropped here while still borrowed
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-2.polonius.stderr b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.polonius.stderr
deleted file mode 100644
index 89af8764557..00000000000
--- a/src/test/ui/borrowck/borrowck-escaping-closure-error-2.polonius.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0597]: `books` does not live long enough
-  --> $DIR/borrowck-escaping-closure-error-2.rs:11:17
-   |
-LL |     Box::new(|| books.push(4))
-   |     ------------^^^^^---------
-   |     |        |  |
-   |     |        |  borrowed value does not live long enough
-   |     |        value captured here
-   |     borrow later used here
-LL |
-LL | }
-   | - `books` dropped here while still borrowed
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.polonius.stderr b/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.polonius.stderr
deleted file mode 100644
index a5b2e876274..00000000000
--- a/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.polonius.stderr
+++ /dev/null
@@ -1,59 +0,0 @@
-error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:5:21
-   |
-LL |     let ref mut x = 1234543;
-   |                     ^^^^^^^ creates a temporary which is freed while still in use
-LL |     x
-   |     - borrow later used here
-LL | }
-   | - temporary value is freed at the end of this statement
-   |
-   = note: consider using a `let` binding to create a longer lived value
-
-error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:10:25
-   |
-LL |     let (ref mut x, ) = (1234543, );
-   |                         ^^^^^^^^^^^ creates a temporary which is freed while still in use
-LL |     x
-   |     - borrow later used here
-LL | }
-   | - temporary value is freed at the end of this statement
-   |
-   = note: consider using a `let` binding to create a longer lived value
-
-error[E0515]: cannot return value referencing temporary value
-  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:15:5
-   |
-LL |       match 1234543 {
-   |       ^     ------- temporary value created here
-   |  _____|
-   | |
-LL | |         ref mut x => x
-LL | |     }
-   | |_____^ returns a value referencing data owned by the current function
-
-error[E0515]: cannot return value referencing temporary value
-  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:21:5
-   |
-LL |       match (123443,) {
-   |       ^     --------- temporary value created here
-   |  _____|
-   | |
-LL | |         (ref mut x,) => x,
-LL | |     }
-   | |_____^ returns a value referencing data owned by the current function
-
-error[E0515]: cannot return reference to temporary value
-  --> $DIR/promote-ref-mut-in-let-issue-46557.rs:27:5
-   |
-LL |     &mut 1234543
-   |     ^^^^^-------
-   |     |    |
-   |     |    temporary value created here
-   |     returns a reference to data owned by the current function
-
-error: aborting due to 5 previous errors
-
-Some errors have detailed explanations: E0515, E0716.
-For more information about an error, try `rustc --explain E0515`.
diff --git a/src/test/ui/borrowck/return-local-binding-from-desugaring.polonius.stderr b/src/test/ui/borrowck/return-local-binding-from-desugaring.polonius.stderr
deleted file mode 100644
index c818379762c..00000000000
--- a/src/test/ui/borrowck/return-local-binding-from-desugaring.polonius.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0716]: temporary value dropped while borrowed
-  --> $DIR/return-local-binding-from-desugaring.rs:26:18
-   |
-LL |     for ref x in xs {
-   |                  ^^ creates a temporary which is freed while still in use
-...
-LL |     }
-   |     - temporary value is freed at the end of this statement
-LL |     result
-   |     ------ borrow later used here
-   |
-   = note: consider using a `let` binding to create a longer lived value
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/borrowck/two-phase-surprise-no-conflict.polonius.stderr b/src/test/ui/borrowck/two-phase-surprise-no-conflict.polonius.stderr
deleted file mode 100644
index 7b246426a23..00000000000
--- a/src/test/ui/borrowck/two-phase-surprise-no-conflict.polonius.stderr
+++ /dev/null
@@ -1,148 +0,0 @@
-error[E0503]: cannot use `self.cx` because it was mutably borrowed
-  --> $DIR/two-phase-surprise-no-conflict.rs:21:23
-   |
-LL |         let _mut_borrow = &mut *self;
-   |                           ---------- borrow of `*self` occurs here
-LL |         let _access = self.cx;
-   |                       ^^^^^^^ use of borrowed `*self`
-LL |
-LL |         _mut_borrow;
-   |         ----------- borrow later used here
-
-error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-surprise-no-conflict.rs:57:17
-   |
-LL |                 self.hash_expr(&self.cx_mut.body(eid).value);
-   |                 ^^^^^---------^^-----------^^^^^^^^^^^^^^^^^
-   |                 |    |          |
-   |                 |    |          immutable borrow occurs here
-   |                 |    immutable borrow later used by call
-   |                 mutable borrow occurs here
-
-error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
-  --> $DIR/two-phase-surprise-no-conflict.rs:119:51
-   |
-LL |     reg.register_static(Box::new(TrivialPass::new(&mut reg.sess_mut)));
-   |     --- ---------------                           ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
-   |     |   |
-   |     |   first borrow later used by call
-   |     first mutable borrow occurs here
-
-error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
-  --> $DIR/two-phase-surprise-no-conflict.rs:122:54
-   |
-LL |     reg.register_bound(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
-   |     --- --------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
-   |     |   |
-   |     |   first borrow later used by call
-   |     first mutable borrow occurs here
-
-error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
-  --> $DIR/two-phase-surprise-no-conflict.rs:125:53
-   |
-LL |     reg.register_univ(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
-   |     --- -------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
-   |     |   |
-   |     |   first borrow later used by call
-   |     first mutable borrow occurs here
-
-error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
-  --> $DIR/two-phase-surprise-no-conflict.rs:128:44
-   |
-LL |     reg.register_ref(&TrivialPass::new_mut(&mut reg.sess_mut));
-   |     --- ------------                       ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
-   |     |   |
-   |     |   first borrow later used by call
-   |     first mutable borrow occurs here
-
-error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-surprise-no-conflict.rs:138:5
-   |
-LL |     reg.register_bound(Box::new(CapturePass::new(&reg.sess_mut)));
-   |     ^^^^--------------^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^^^
-   |     |   |                                        |
-   |     |   |                                        immutable borrow occurs here
-   |     |   immutable borrow later used by call
-   |     mutable borrow occurs here
-
-error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-surprise-no-conflict.rs:141:5
-   |
-LL |     reg.register_univ(Box::new(CapturePass::new(&reg.sess_mut)));
-   |     ^^^^-------------^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^^^
-   |     |   |                                       |
-   |     |   |                                       immutable borrow occurs here
-   |     |   immutable borrow later used by call
-   |     mutable borrow occurs here
-
-error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-surprise-no-conflict.rs:144:5
-   |
-LL |     reg.register_ref(&CapturePass::new(&reg.sess_mut));
-   |     ^^^^------------^^^^^^^^^^^^^^^^^^^-------------^^
-   |     |   |                              |
-   |     |   |                              immutable borrow occurs here
-   |     |   immutable borrow later used by call
-   |     mutable borrow occurs here
-
-error[E0499]: cannot borrow `*reg` as mutable more than once at a time
-  --> $DIR/two-phase-surprise-no-conflict.rs:154:5
-   |
-LL |     reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
-   |     ^^^^--------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^^
-   |     |   |                                            |
-   |     |   |                                            first mutable borrow occurs here
-   |     |   first borrow later used by call
-   |     second mutable borrow occurs here
-
-error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
-  --> $DIR/two-phase-surprise-no-conflict.rs:154:54
-   |
-LL |     reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
-   |     --- --------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
-   |     |   |
-   |     |   first borrow later used by call
-   |     first mutable borrow occurs here
-
-error[E0499]: cannot borrow `*reg` as mutable more than once at a time
-  --> $DIR/two-phase-surprise-no-conflict.rs:158:5
-   |
-LL |     reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
-   |     ^^^^-------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^^
-   |     |   |                                           |
-   |     |   |                                           first mutable borrow occurs here
-   |     |   first borrow later used by call
-   |     second mutable borrow occurs here
-
-error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
-  --> $DIR/two-phase-surprise-no-conflict.rs:158:53
-   |
-LL |     reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
-   |     --- -------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
-   |     |   |
-   |     |   first borrow later used by call
-   |     first mutable borrow occurs here
-
-error[E0499]: cannot borrow `*reg` as mutable more than once at a time
-  --> $DIR/two-phase-surprise-no-conflict.rs:162:5
-   |
-LL |     reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut));
-   |     ^^^^------------^^^^^^^^^^^^^^^^^^^^^^^-----------------^^
-   |     |   |                                  |
-   |     |   |                                  first mutable borrow occurs here
-   |     |   first borrow later used by call
-   |     second mutable borrow occurs here
-
-error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
-  --> $DIR/two-phase-surprise-no-conflict.rs:162:44
-   |
-LL |     reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut));
-   |     --- ------------                       ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
-   |     |   |
-   |     |   first borrow later used by call
-   |     first mutable borrow occurs here
-
-error: aborting due to 15 previous errors
-
-Some errors have detailed explanations: E0499, E0502, E0503.
-For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/consts/promote_const_let.polonius.stderr b/src/test/ui/consts/promote_const_let.polonius.stderr
deleted file mode 100644
index cf41bd7bdb1..00000000000
--- a/src/test/ui/consts/promote_const_let.polonius.stderr
+++ /dev/null
@@ -1,29 +0,0 @@
-error[E0597]: `y` does not live long enough
-  --> $DIR/promote_const_let.rs:4:9
-   |
-LL |     let x: &'static u32 = {
-   |         - borrow later stored here
-LL |         let y = 42;
-LL |         &y
-   |         ^^ borrowed value does not live long enough
-LL |     };
-   |     - `y` dropped here while still borrowed
-
-error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote_const_let.rs:6:28
-   |
-LL |       let x: &'static u32 = &{
-   |  ____________------------____^
-   | |            |
-   | |            type annotation requires that borrow lasts for `'static`
-LL | |         let y = 42;
-LL | |         y
-LL | |     };
-   | |_____^ creates a temporary which is freed while still in use
-LL |   }
-   |   - temporary value is freed at the end of this statement
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0597, E0716.
-For more information about an error, try `rustc --explain E0597`.
diff --git a/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr b/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr
deleted file mode 100644
index 5e93a023425..00000000000
--- a/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr
+++ /dev/null
@@ -1,78 +0,0 @@
-error[E0597]: `o2` does not live long enough
-  --> $DIR/dropck_trait_cycle_checked.rs:111:13
-   |
-LL |     o1.set0(&o2);
-   |             ^^^ borrowed value does not live long enough
-...
-LL | }
-   | -
-   | |
-   | `o2` dropped here while still borrowed
-   | borrow might be used here, when `o1` is dropped and runs the destructor for type `std::boxed::Box<dyn Obj<'_>>`
-   |
-   = note: values in a scope are dropped in the opposite order they are defined
-
-error[E0597]: `o3` does not live long enough
-  --> $DIR/dropck_trait_cycle_checked.rs:112:13
-   |
-LL |     o1.set1(&o3);
-   |             ^^^ borrowed value does not live long enough
-...
-LL | }
-   | -
-   | |
-   | `o3` dropped here while still borrowed
-   | borrow might be used here, when `o1` is dropped and runs the destructor for type `std::boxed::Box<dyn Obj<'_>>`
-   |
-   = note: values in a scope are dropped in the opposite order they are defined
-
-error[E0597]: `o2` does not live long enough
-  --> $DIR/dropck_trait_cycle_checked.rs:113:13
-   |
-LL |     let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
-   |                                                                               -------- cast requires that `o2` is borrowed for `'static`
-...
-LL |     o2.set0(&o2);
-   |             ^^^ borrowed value does not live long enough
-...
-LL | }
-   | - `o2` dropped here while still borrowed
-
-error[E0597]: `o3` does not live long enough
-  --> $DIR/dropck_trait_cycle_checked.rs:114:13
-   |
-LL |     let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
-   |                                                                               -------- cast requires that `o3` is borrowed for `'static`
-...
-LL |     o2.set1(&o3);
-   |             ^^^ borrowed value does not live long enough
-...
-LL | }
-   | - `o3` dropped here while still borrowed
-
-error[E0597]: `o1` does not live long enough
-  --> $DIR/dropck_trait_cycle_checked.rs:115:13
-   |
-LL |     o3.set0(&o1);
-   |             ^^^ borrowed value does not live long enough
-LL |     o3.set1(&o2);
-LL | }
-   | -
-   | |
-   | `o1` dropped here while still borrowed
-   | borrow might be used here, when `o1` is dropped and runs the destructor for type `std::boxed::Box<dyn Obj<'_>>`
-
-error[E0597]: `o2` does not live long enough
-  --> $DIR/dropck_trait_cycle_checked.rs:116:13
-   |
-LL |     let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
-   |                                                                                         -------- cast requires that `o2` is borrowed for `'static`
-...
-LL |     o3.set1(&o2);
-   |             ^^^ borrowed value does not live long enough
-LL | }
-   | - `o2` dropped here while still borrowed
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/generator/ref-escapes-but-not-over-yield.polonius.stderr b/src/test/ui/generator/ref-escapes-but-not-over-yield.polonius.stderr
deleted file mode 100644
index 530bf368f67..00000000000
--- a/src/test/ui/generator/ref-escapes-but-not-over-yield.polonius.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0597]: `b` does not live long enough
-  --> $DIR/ref-escapes-but-not-over-yield.rs:11:13
-   |
-LL |       let mut b = move || {
-   |  _________________-
-LL | |         yield();
-LL | |         let b = 5;
-LL | |         a = &b;
-   | |             ^^ borrowed value does not live long enough
-LL | |
-LL | |     };
-   | |     -
-   | |     |
-   | |     `b` dropped here while still borrowed
-   | |_____... and the borrow might be used here, when that temporary is dropped and runs the destructor for generator
-   |       a temporary with access to the borrow is created here ...
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/get_default.polonius.stderr b/src/test/ui/nll/get_default.polonius.stderr
index 2df6d5d61fc..476d86cfba9 100644
--- a/src/test/ui/nll/get_default.polonius.stderr
+++ b/src/test/ui/nll/get_default.polonius.stderr
@@ -1,6 +1,9 @@
 error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable
   --> $DIR/get_default.rs:32:17
    |
+LL | fn err(map: &mut Map) -> &String {
+   |             - let's call the lifetime of this reference `'1`
+LL |     loop {
 LL |         match map.get() {
    |               --- immutable borrow occurs here
 LL |             Some(v) => {
@@ -8,7 +11,7 @@ LL |                 map.set(String::new()); // Both AST and MIR error here
    |                 ^^^ mutable borrow occurs here
 LL |
 LL |                 return v;
-   |                        - immutable borrow later used here
+   |                        - returning this value requires that `*map` is borrowed for `'1`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/loan_ends_mid_block_pair.polonius.stderr b/src/test/ui/nll/loan_ends_mid_block_pair.polonius.stderr
deleted file mode 100644
index eb8442b31d7..00000000000
--- a/src/test/ui/nll/loan_ends_mid_block_pair.polonius.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0506]: cannot assign to `data.0` because it is borrowed
-  --> $DIR/loan_ends_mid_block_pair.rs:12:5
-   |
-LL |     let c = &mut data.0;
-   |             ----------- borrow of `data.0` occurs here
-LL |     capitalize(c);
-LL |     data.0 = 'e';
-   |     ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here
-...
-LL |     capitalize(c);
-   |                - borrow later used here
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/polonius/polonius-smoke-test.stderr b/src/test/ui/nll/polonius/polonius-smoke-test.stderr
index dbc5b7a019a..1faf8e2212a 100644
--- a/src/test/ui/nll/polonius/polonius-smoke-test.stderr
+++ b/src/test/ui/nll/polonius/polonius-smoke-test.stderr
@@ -17,12 +17,14 @@ LL |     let w = y;
 error[E0505]: cannot move out of `x` because it is borrowed
   --> $DIR/polonius-smoke-test.rs:19:13
    |
+LL | pub fn use_while_mut_fr(x: &mut i32) -> &mut i32 {
+   |                            - let's call the lifetime of this reference `'1`
 LL |     let y = &mut *x;
    |             ------- borrow of `*x` occurs here
 LL |     let z = x;
    |             ^ move out of `x` occurs here
 LL |     y
-   |     - borrow later used here
+   |     - returning this value requires that `*x` is borrowed for `'1`
 
 error[E0505]: cannot move out of `s` because it is borrowed
   --> $DIR/polonius-smoke-test.rs:43:5
diff --git a/src/test/ui/nll/return-ref-mut-issue-46557.polonius.stderr b/src/test/ui/nll/return-ref-mut-issue-46557.polonius.stderr
deleted file mode 100644
index 8e3cf59cffb..00000000000
--- a/src/test/ui/nll/return-ref-mut-issue-46557.polonius.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0716]: temporary value dropped while borrowed
-  --> $DIR/return-ref-mut-issue-46557.rs:4:21
-   |
-LL |     let ref mut x = 1234543;
-   |                     ^^^^^^^ creates a temporary which is freed while still in use
-LL |     x
-   |     - borrow later used here
-LL | }
-   | - temporary value is freed at the end of this statement
-   |
-   = note: consider using a `let` binding to create a longer lived value
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.polonius.stderr b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.polonius.stderr
deleted file mode 100644
index 4b906f75149..00000000000
--- a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.polonius.stderr
+++ /dev/null
@@ -1,60 +0,0 @@
-error[E0597]: `factorial` does not live long enough
-  --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:15:17
-   |
-LL |     let f = |x: u32| -> u32 {
-   |             --------------- value captured here
-LL |         let g = factorial.as_ref().unwrap();
-   |                 ^^^^^^^^^ borrowed value does not live long enough
-...
-LL | }
-   | -
-   | |
-   | `factorial` dropped here while still borrowed
-   | borrow might be used here, when `factorial` is dropped and runs the destructor for type `std::option::Option<std::boxed::Box<dyn std::ops::Fn(u32) -> u32>>`
-
-error[E0506]: cannot assign to `factorial` because it is borrowed
-  --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:20:5
-   |
-LL |     let f = |x: u32| -> u32 {
-   |             --------------- borrow of `factorial` occurs here
-LL |         let g = factorial.as_ref().unwrap();
-   |                 --------- borrow occurs due to use in closure
-...
-LL |     factorial = Some(Box::new(f));
-   |     ^^^^^^^^^
-   |     |
-   |     assignment to borrowed `factorial` occurs here
-   |     borrow later used here
-
-error[E0597]: `factorial` does not live long enough
-  --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:28:17
-   |
-LL |     let f = |x: u32| -> u32 {
-   |             --------------- value captured here
-LL |         let g = factorial.as_ref().unwrap();
-   |                 ^^^^^^^^^ borrowed value does not live long enough
-...
-LL | }
-   | -
-   | |
-   | `factorial` dropped here while still borrowed
-   | borrow might be used here, when `factorial` is dropped and runs the destructor for type `std::option::Option<std::boxed::Box<dyn std::ops::Fn(u32) -> u32>>`
-
-error[E0506]: cannot assign to `factorial` because it is borrowed
-  --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:33:5
-   |
-LL |     let f = |x: u32| -> u32 {
-   |             --------------- borrow of `factorial` occurs here
-LL |         let g = factorial.as_ref().unwrap();
-   |                 --------- borrow occurs due to use in closure
-...
-LL |     factorial = Some(Box::new(f));
-   |     ^^^^^^^^^
-   |     |
-   |     assignment to borrowed `factorial` occurs here
-   |     borrow later used here
-
-error: aborting due to 4 previous errors
-
-Some errors have detailed explanations: E0506, E0597.
-For more information about an error, try `rustc --explain E0506`.

From 2180c243214ebce29c45c37020e929924a8520d8 Mon Sep 17 00:00:00 2001
From: Matthew Jasper <mjjasper1@gmail.com>
Date: Tue, 24 Sep 2019 21:55:49 +0100
Subject: [PATCH 2/2] Make lifetimes in constants live at the point of use

---
 .../borrow_check/nll/type_check/mod.rs        | 64 ++++++++++++-------
 .../ui/hrtb/due-to-where-clause.nll.stderr    |  8 +++
 src/test/ui/hrtb/due-to-where-clause.rs       |  3 -
 src/test/ui/hrtb/due-to-where-clause.stderr   |  2 +-
 src/test/ui/nll/promoted-liveness.rs          |  8 +++
 5 files changed, 58 insertions(+), 27 deletions(-)
 create mode 100644 src/test/ui/hrtb/due-to-where-clause.nll.stderr
 create mode 100644 src/test/ui/nll/promoted-liveness.rs

diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index b24ba596d7e..adc3381a1e7 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -276,7 +276,17 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
 
     fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
         self.super_constant(constant, location);
-        self.sanitize_type(constant, constant.literal.ty);
+        let ty = self.sanitize_type(constant, constant.literal.ty);
+
+        self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| {
+            let live_region_vid =
+                self.cx.borrowck_context.universal_regions.to_region_vid(live_region);
+            self.cx
+                .borrowck_context
+                .constraints
+                .liveness_constraints
+                .add_element(live_region_vid, location);
+        });
 
         if let Some(annotation_index) = constant.user_ty {
             if let Err(terr) = self.cx.relate_type_and_user_type(
@@ -528,25 +538,37 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
 
         let parent_body = mem::replace(&mut self.body, promoted_body);
 
+        // Use new sets of constraints and closure bounds so that we can
+        // modify their locations.
         let all_facts = &mut None;
         let mut constraints = Default::default();
         let mut closure_bounds = Default::default();
+        let mut liveness_constraints = LivenessValues::new(
+            Rc::new(RegionValueElements::new(promoted_body)),
+        );
         // Don't try to add borrow_region facts for the promoted MIR
-        mem::swap(self.cx.borrowck_context.all_facts, all_facts);
 
-        // Use a new sets of constraints and closure bounds so that we can
-        // modify their locations.
-        mem::swap(
-            &mut self.cx.borrowck_context.constraints.outlives_constraints,
-            &mut constraints
-        );
-        mem::swap(
-            &mut self.cx.borrowck_context.constraints.closure_bounds_mapping,
-            &mut closure_bounds
-        );
+        let mut swap_constraints = |this: &mut Self| {
+            mem::swap(this.cx.borrowck_context.all_facts, all_facts);
+            mem::swap(
+                &mut this.cx.borrowck_context.constraints.outlives_constraints,
+                &mut constraints
+            );
+            mem::swap(
+                &mut this.cx.borrowck_context.constraints.closure_bounds_mapping,
+                &mut closure_bounds
+            );
+            mem::swap(
+                &mut this.cx.borrowck_context.constraints.liveness_constraints,
+                &mut liveness_constraints
+            );
+        };
+
+        swap_constraints(self);
 
         self.visit_body(promoted_body);
 
+
         if !self.errors_reported {
             // if verifier failed, don't do further checks to avoid ICEs
             self.cx.typeck_mir(promoted_body);
@@ -554,23 +576,15 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
 
         self.body = parent_body;
         // Merge the outlives constraints back in, at the given location.
-        mem::swap(self.cx.borrowck_context.all_facts, all_facts);
-        mem::swap(
-            &mut self.cx.borrowck_context.constraints.outlives_constraints,
-            &mut constraints
-        );
-        mem::swap(
-            &mut self.cx.borrowck_context.constraints.closure_bounds_mapping,
-            &mut closure_bounds
-        );
+        swap_constraints(self);
 
         let locations = location.to_locations();
         for constraint in constraints.outlives().iter() {
             let mut constraint = *constraint;
             constraint.locations = locations;
             if let ConstraintCategory::Return
-                | ConstraintCategory::UseAsConst
-                | ConstraintCategory::UseAsStatic = constraint.category
+            | ConstraintCategory::UseAsConst
+            | ConstraintCategory::UseAsStatic = constraint.category
             {
                 // "Returning" from a promoted is an assigment to a
                 // temporary from the user's point of view.
@@ -578,6 +592,10 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
             }
             self.cx.borrowck_context.constraints.outlives_constraints.push(constraint)
         }
+        for live_region in liveness_constraints.rows() {
+            self.cx.borrowck_context.constraints.liveness_constraints
+                .add_element(live_region, location);
+        }
 
         if !closure_bounds.is_empty() {
             let combined_bounds_mapping = closure_bounds
diff --git a/src/test/ui/hrtb/due-to-where-clause.nll.stderr b/src/test/ui/hrtb/due-to-where-clause.nll.stderr
new file mode 100644
index 00000000000..e476047a7a6
--- /dev/null
+++ b/src/test/ui/hrtb/due-to-where-clause.nll.stderr
@@ -0,0 +1,8 @@
+error: higher-ranked subtype error
+  --> $DIR/due-to-where-clause.rs:2:5
+   |
+LL |     test::<FooS>(&mut 42);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hrtb/due-to-where-clause.rs b/src/test/ui/hrtb/due-to-where-clause.rs
index 04e2ddd4a60..1afd15613b5 100644
--- a/src/test/ui/hrtb/due-to-where-clause.rs
+++ b/src/test/ui/hrtb/due-to-where-clause.rs
@@ -1,6 +1,3 @@
-// ignore-compare-mode-nll
-// ^ This code works in nll mode.
-
 fn main() {
     test::<FooS>(&mut 42); //~ ERROR implementation of `Foo` is not general enough
 }
diff --git a/src/test/ui/hrtb/due-to-where-clause.stderr b/src/test/ui/hrtb/due-to-where-clause.stderr
index 9fef1e33543..e4096ec059a 100644
--- a/src/test/ui/hrtb/due-to-where-clause.stderr
+++ b/src/test/ui/hrtb/due-to-where-clause.stderr
@@ -1,5 +1,5 @@
 error: implementation of `Foo` is not general enough
-  --> $DIR/due-to-where-clause.rs:5:5
+  --> $DIR/due-to-where-clause.rs:2:5
    |
 LL |     test::<FooS>(&mut 42);
    |     ^^^^^^^^^^^^ implementation of `Foo` is not general enough
diff --git a/src/test/ui/nll/promoted-liveness.rs b/src/test/ui/nll/promoted-liveness.rs
new file mode 100644
index 00000000000..e5a8e1e5c2f
--- /dev/null
+++ b/src/test/ui/nll/promoted-liveness.rs
@@ -0,0 +1,8 @@
+// Test that promoted that have larger mir bodies than their containing function
+// don't cause an ICE.
+
+// check-pass
+
+fn main() {
+    &["0", "1", "2", "3", "4", "5", "6", "7"];
+}