about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2018-07-01 19:43:01 -0300
committerSantiago Pastorino <spastorino@gmail.com>2018-07-01 20:46:07 -0300
commit0957ede5027c0bffe208904998675a17bfd4cd59 (patch)
treec453480ba2599e5f99cd5e4c099d4bedc112ed74 /src
parent24f91e878244990595649120f402cc13263ae54f (diff)
downloadrust-0957ede5027c0bffe208904998675a17bfd4cd59.tar.gz
rust-0957ede5027c0bffe208904998675a17bfd4cd59.zip
Make causal tracking lazy
Diffstat (limited to 'src')
-rw-r--r--src/librustc/mir/mod.rs29
-rw-r--r--src/librustc_mir/borrow_check/nll/constraint_generation.rs26
-rw-r--r--src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs174
-rw-r--r--src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs121
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting.rs15
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/mod.rs18
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/values.rs84
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/liveness.rs10
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs4
-rw-r--r--src/test/ui/generator/borrowing.nll.stderr9
-rw-r--r--src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr18
-rw-r--r--src/test/ui/issue-47646.stderr8
-rw-r--r--src/test/ui/span/destructor-restrictions.nll.stderr9
-rw-r--r--src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr19
14 files changed, 225 insertions, 319 deletions
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index dec37bdf719..dca0d4f442a 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -1000,6 +1000,10 @@ impl<'tcx> Terminator<'tcx> {
         self.kind.successors_mut()
     }
 
+    pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
+        self.kind.unwind()
+    }
+
     pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
         self.kind.unwind_mut()
     }
@@ -1195,6 +1199,31 @@ impl<'tcx> TerminatorKind<'tcx> {
         }
     }
 
+    pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
+        match *self {
+            TerminatorKind::Goto { .. }
+            | TerminatorKind::Resume
+            | TerminatorKind::Abort
+            | TerminatorKind::Return
+            | TerminatorKind::Unreachable
+            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::Yield { .. }
+            | TerminatorKind::SwitchInt { .. }
+            | TerminatorKind::FalseEdges { .. } => None,
+            TerminatorKind::Call {
+                cleanup: ref unwind,
+                ..
+            }
+            | TerminatorKind::Assert {
+                cleanup: ref unwind,
+                ..
+            }
+            | TerminatorKind::DropAndReplace { ref unwind, .. }
+            | TerminatorKind::Drop { ref unwind, .. }
+            | TerminatorKind::FalseUnwind { ref unwind, .. } => Some(unwind),
+        }
+    }
+
     pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
         match *self {
             TerminatorKind::Goto { .. }
diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
index 68aa9aeabf8..25a0123755f 100644
--- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
@@ -12,7 +12,7 @@ use borrow_check::borrow_set::BorrowSet;
 use borrow_check::location::LocationTable;
 use borrow_check::nll::ToRegionVid;
 use borrow_check::nll::facts::AllFacts;
-use borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
+use borrow_check::nll::region_infer::RegionInferenceContext;
 use borrow_check::nll::type_check::AtLocation;
 use rustc::hir;
 use rustc::infer::InferCtxt;
@@ -33,7 +33,7 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
     location_table: &LocationTable,
     mir: &Mir<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
-    liveness_set_from_typeck: &[(ty::Region<'tcx>, Location, Cause)],
+    liveness_set_from_typeck: &[(ty::Region<'tcx>, Location)],
 ) {
     let mut cg = ConstraintGeneration {
         borrow_set,
@@ -69,14 +69,14 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
     /// We sometimes have `substs` within an rvalue, or within a
     /// call. Make them live at the location where they appear.
     fn visit_substs(&mut self, substs: &&'tcx Substs<'tcx>, location: Location) {
-        self.add_regular_live_constraint(*substs, location, Cause::LiveOther(location));
+        self.add_regular_live_constraint(*substs, location);
         self.super_substs(substs);
     }
 
     /// We sometimes have `region` within an rvalue, or within a
     /// call. Make them live at the location where they appear.
     fn visit_region(&mut self, region: &ty::Region<'tcx>, location: Location) {
-        self.add_regular_live_constraint(*region, location, Cause::LiveOther(location));
+        self.add_regular_live_constraint(*region, location);
         self.super_region(region);
     }
 
@@ -94,7 +94,7 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
                 );
             }
             TyContext::Location(location) => {
-                self.add_regular_live_constraint(*ty, location, Cause::LiveOther(location));
+                self.add_regular_live_constraint(*ty, location);
             }
         }
 
@@ -104,14 +104,14 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
     /// We sometimes have `generator_substs` within an rvalue, or within a
     /// call. Make them live at the location where they appear.
     fn visit_generator_substs(&mut self, substs: &GeneratorSubsts<'tcx>, location: Location) {
-        self.add_regular_live_constraint(*substs, location, Cause::LiveOther(location));
+        self.add_regular_live_constraint(*substs, location);
         self.super_generator_substs(substs);
     }
 
     /// We sometimes have `closure_substs` within an rvalue, or within a
     /// call. Make them live at the location where they appear.
     fn visit_closure_substs(&mut self, substs: &ClosureSubsts<'tcx>, location: Location) {
-        self.add_regular_live_constraint(*substs, location, Cause::LiveOther(location));
+        self.add_regular_live_constraint(*substs, location);
         self.super_closure_substs(substs);
     }
 
@@ -233,7 +233,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
     /// that we also have to respect.
     fn add_region_liveness_constraints_from_type_check(
         &mut self,
-        liveness_set: &[(ty::Region<'tcx>, Location, Cause)],
+        liveness_set: &[(ty::Region<'tcx>, Location)],
     ) {
         debug!(
             "add_region_liveness_constraints_from_type_check(liveness_set={} items)",
@@ -247,16 +247,16 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
             ..
         } = self;
 
-        for (region, location, cause) in liveness_set {
+        for (region, location) in liveness_set {
             debug!("generate: {:#?} is live at {:#?}", region, location);
             let region_vid = regioncx.to_region_vid(region);
-            regioncx.add_live_point(region_vid, *location, &cause);
+            regioncx.add_live_point(region_vid, *location);
         }
 
         if let Some(all_facts) = all_facts {
             all_facts
                 .region_live_at
-                .extend(liveness_set.into_iter().flat_map(|(region, location, _)| {
+                .extend(liveness_set.into_iter().flat_map(|(region, location)| {
                     let r = regioncx.to_region_vid(region);
                     let p1 = location_table.start_index(*location);
                     let p2 = location_table.mid_index(*location);
@@ -269,7 +269,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
     /// `location` -- i.e., it may be used later. This means that all
     /// regions appearing in the type `live_ty` must be live at
     /// `location`.
-    fn add_regular_live_constraint<T>(&mut self, live_ty: T, location: Location, cause: Cause)
+    fn add_regular_live_constraint<T>(&mut self, live_ty: T, location: Location)
     where
         T: TypeFoldable<'tcx>,
     {
@@ -282,7 +282,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
             .tcx
             .for_each_free_region(&live_ty, |live_region| {
                 let vid = live_region.to_region_vid();
-                self.regioncx.add_live_point(vid, location, &cause);
+                self.regioncx.add_live_point(vid, location);
             });
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs
index 58e9d814826..a65019690e3 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs
@@ -8,50 +8,32 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use borrow_check::borrow_set::BorrowData;
-use borrow_check::nll::region_infer::RegionInferenceContext;
+use std::collections::VecDeque;
+use std::rc::Rc;
+
+use borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
+use borrow_check::nll::ToRegionVid;
 use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor};
 use rustc::mir::{Local, Location, Mir};
+use rustc::ty::{RegionVid, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
 use util::liveness::{self, DefUse, LivenessMode};
 
-crate fn regular_use<'gcx, 'tcx>(
-    mir: &'gcx Mir,
-    regioncx: &'tcx RegionInferenceContext,
-    borrow: &'tcx BorrowData,
+crate fn find<'cx, 'gcx: 'tcx, 'tcx: 'cx>(
+    mir: &'cx Mir<'tcx>,
+    regioncx: &'cx Rc<RegionInferenceContext<'tcx>>,
+    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+    region_vid: RegionVid,
     start_point: Location,
-    local: Local,
-) -> Option<Location> {
+) -> Option<Cause> {
     let mut uf = UseFinder {
         mir,
         regioncx,
-        borrow,
+        tcx,
+        region_vid,
         start_point,
-        local,
         liveness_mode: LivenessMode {
             include_regular_use: true,
-            include_drops: false,
-        },
-    };
-
-    uf.find()
-}
-
-crate fn drop_use<'gcx, 'tcx>(
-    mir: &'gcx Mir,
-    regioncx: &'tcx RegionInferenceContext,
-    borrow: &'tcx BorrowData,
-    start_point: Location,
-    local: Local,
-) -> Option<Location> {
-    let mut uf = UseFinder {
-        mir,
-        regioncx,
-        borrow,
-        start_point,
-        local,
-        liveness_mode: LivenessMode {
-            include_regular_use: false,
             include_drops: true,
         },
     };
@@ -59,23 +41,23 @@ crate fn drop_use<'gcx, 'tcx>(
     uf.find()
 }
 
-struct UseFinder<'gcx, 'tcx> {
-    mir: &'gcx Mir<'gcx>,
-    regioncx: &'tcx RegionInferenceContext<'tcx>,
-    borrow: &'tcx BorrowData<'tcx>,
+struct UseFinder<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
+    mir: &'cx Mir<'tcx>,
+    regioncx: &'cx Rc<RegionInferenceContext<'tcx>>,
+    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+    region_vid: RegionVid,
     start_point: Location,
-    local: Local,
     liveness_mode: LivenessMode,
 }
 
-impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> {
-    fn find(&mut self) -> Option<Location> {
-        let mut stack = vec![];
+impl<'cx, 'gcx, 'tcx> UseFinder<'cx, 'gcx, 'tcx> {
+    fn find(&mut self) -> Option<Cause> {
+        let mut queue = VecDeque::new();
         let mut visited = FxHashSet();
 
-        stack.push(self.start_point);
-        while let Some(p) = stack.pop() {
-            if !self.regioncx.region_contains_point(self.borrow.region, p) {
+        queue.push_back(self.start_point);
+        while let Some(p) = queue.pop_front() {
+            if !self.regioncx.region_contains_point(self.region_vid, p) {
                 continue;
             }
 
@@ -84,23 +66,36 @@ impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> {
             }
 
             let block_data = &self.mir[p.block];
-            let (defined, used) = self.def_use(p, block_data.visitable(p.statement_index));
-
-            if used {
-                return Some(p);
-            } else if !defined {
-                if p.statement_index < block_data.statements.len() {
-                    stack.push(Location {
-                        statement_index: p.statement_index + 1,
-                        ..p
-                    });
-                } else {
-                    stack.extend(block_data.terminator().successors().map(|&basic_block| {
-                        Location {
-                            statement_index: 0,
-                            block: basic_block,
-                        }
-                    }));
+
+            match self.def_use(p, block_data.visitable(p.statement_index)) {
+                Some(DefUseResult::Def) => {}
+
+                Some(DefUseResult::UseLive { local }) => {
+                    return Some(Cause::LiveVar(local, p));
+                }
+
+                Some(DefUseResult::UseDrop { local }) => {
+                    return Some(Cause::DropVar(local, p));
+                }
+
+                None => {
+                    if p.statement_index < block_data.statements.len() {
+                        queue.push_back(Location {
+                            statement_index: p.statement_index + 1,
+                            ..p
+                        });
+                    } else {
+                        queue.extend(
+                            block_data
+                                .terminator()
+                                .successors()
+                                .filter(|&bb| Some(&Some(*bb)) != block_data.terminator().unwind())
+                                .map(|&bb| Location {
+                                    statement_index: 0,
+                                    block: bb,
+                                }),
+                        );
+                    }
                 }
             }
         }
@@ -108,34 +103,65 @@ impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> {
         None
     }
 
-    fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> (bool, bool) {
+    fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> Option<DefUseResult> {
         let mut visitor = DefUseVisitor {
-            defined: false,
-            used: false,
-            local: self.local,
+            mir: self.mir,
+            tcx: self.tcx,
+            region_vid: self.region_vid,
             liveness_mode: self.liveness_mode,
+            def_use_result: None,
         };
 
         thing.apply(location, &mut visitor);
 
-        (visitor.defined, visitor.used)
+        visitor.def_use_result
     }
 }
 
-struct DefUseVisitor {
-    defined: bool,
-    used: bool,
-    local: Local,
+struct DefUseVisitor<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
+    mir: &'cx Mir<'tcx>,
+    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+    region_vid: RegionVid,
     liveness_mode: LivenessMode,
+    def_use_result: Option<DefUseResult>,
+}
+
+enum DefUseResult {
+    Def,
+
+    UseLive { local: Local },
+
+    UseDrop { local: Local },
 }
 
-impl<'tcx> Visitor<'tcx> for DefUseVisitor {
+impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'gcx, 'tcx> {
     fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Location) {
-        if local == self.local {
+        let local_ty = self.mir.local_decls[local].ty;
+
+        let mut found_it = false;
+        self.tcx.for_each_free_region(&local_ty, |r| {
+            if r.to_region_vid() == self.region_vid {
+                found_it = true;
+            }
+        });
+
+        if found_it {
             match liveness::categorize(context, self.liveness_mode) {
-                Some(DefUse::Def) => self.defined = true,
-                Some(DefUse::Use) => self.used = true,
-                None => (),
+                Some(DefUse::Def) => {
+                    self.def_use_result = Some(DefUseResult::Def);
+                }
+
+                Some(DefUse::Use) => {
+                    self.def_use_result = if context.is_drop() {
+                        Some(DefUseResult::UseDrop { local })
+                    } else {
+                        Some(DefUseResult::UseLive { local })
+                    };
+                }
+
+                None => {
+                    self.def_use_result = None;
+                }
             }
         }
     }
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
index acc164b14c3..bc4646b7c78 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
@@ -38,87 +38,72 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         kind_place: Option<(WriteKind, &Place<'tcx>)>,
         err: &mut DiagnosticBuilder<'_>,
     ) {
-        let regioncx = &&self.nonlexical_regioncx;
+        debug!(
+            "explain_why_borrow_contains_point(context={:?}, borrow={:?}, kind_place={:?})",
+            context, borrow, kind_place,
+        );
+
+        let regioncx = &self.nonlexical_regioncx;
         let mir = self.mir;
+        let tcx = self.tcx;
 
         let borrow_region_vid = regioncx.to_region_vid(borrow.region);
-        if let Some(cause) = regioncx.why_region_contains_point(borrow_region_vid, context.loc) {
-            match cause {
-                Cause::LiveVar(local, location) => match find_use::regular_use(
-                    mir, regioncx, borrow, location, local,
-                ) {
-                    Some(p) => {
-                        err.span_label(mir.source_info(p).span, format!("borrow later used here"));
-                    }
 
-                    None => {
-                        span_bug!(
-                            mir.source_info(context.loc).span,
-                            "Cause should end in a LiveVar"
-                        );
-                    }
-                },
+        debug!(
+            "explain_why_borrow_contains_point: borrow_region_vid={:?}",
+            borrow_region_vid
+        );
 
-                Cause::DropVar(local, location) => match find_use::drop_use(
-                    mir, regioncx, borrow, location, local,
-                ) {
-                    Some(p) => match &mir.local_decls[local].name {
-                        Some(local_name) => {
-                            err.span_label(
-                                mir.source_info(p).span,
-                                format!("borrow later used here, when `{}` is dropped", local_name),
-                            );
+        let region_sub = regioncx.find_constraint(borrow_region_vid, context.loc);
 
-                            if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
-                                if let Place::Local(borrowed_local) = place {
-                                    let dropped_local_scope =
-                                        mir.local_decls[local].visibility_scope;
-                                    let borrowed_local_scope =
-                                        mir.local_decls[*borrowed_local].visibility_scope;
+        debug!(
+            "explain_why_borrow_contains_point: region_sub={:?}",
+            region_sub
+        );
 
-                                    if mir.is_sub_scope(borrowed_local_scope, dropped_local_scope) {
-                                        err.note(
-                                            "values in a scope are dropped \
-                                             in the opposite order they are defined",
-                                        );
-                                    }
-                                }
-                            }
-                        }
-                        None => {
-                            err.span_label(
-                                mir.local_decls[local].source_info.span,
-                                "borrow may end up in a temporary, created here",
-                            );
+        match find_use::find(mir, regioncx, tcx, region_sub, context.loc) {
+            Some(Cause::LiveVar(_local, location)) => {
+                err.span_label(
+                    mir.source_info(location).span,
+                    format!("borrow later used here"),
+                );
+            }
 
-                            err.span_label(
-                                mir.source_info(p).span,
-                                "temporary later dropped here, \
-                                 potentially using the reference",
-                            );
-                        }
-                    },
+            Some(Cause::DropVar(local, location)) => match &mir.local_decls[local].name {
+                Some(local_name) => {
+                    err.span_label(
+                        mir.source_info(location).span,
+                        format!("borrow later used here, when `{}` is dropped", local_name),
+                    );
 
-                    None => {
-                        span_bug!(
-                            mir.source_info(context.loc).span,
-                            "Cause should end in a DropVar"
-                        );
-                    }
-                },
+                    if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
+                        if let Place::Local(borrowed_local) = place {
+                            let dropped_local_scope = mir.local_decls[local].visibility_scope;
+                            let borrowed_local_scope =
+                                mir.local_decls[*borrowed_local].visibility_scope;
 
-                Cause::UniversalRegion(region_vid) => {
-                    if let Some(region) = regioncx.to_error_region(region_vid) {
-                        self.tcx.note_and_explain_free_region(
-                            err,
-                            "borrowed value must be valid for ",
-                            region,
-                            "...",
-                        );
+                            if mir.is_sub_scope(borrowed_local_scope, dropped_local_scope) {
+                                err.note(
+                                    "values in a scope are dropped \
+                                     in the opposite order they are defined",
+                                );
+                            }
+                        }
                     }
                 }
 
-                _ => {}
+                None => {}
+            },
+
+            None => {
+                if let Some(region) = regioncx.to_error_region(region_sub) {
+                    self.tcx.note_and_explain_free_region(
+                        err,
+                        "borrowed value must be valid for ",
+                        region,
+                        "...",
+                    );
+                }
             }
         }
     }
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting.rs
index 970652d8872..6543516b9c2 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::fmt;
-use borrow_check::nll::region_infer::{Cause, ConstraintIndex, RegionInferenceContext};
+use borrow_check::nll::region_infer::{ConstraintIndex, RegionInferenceContext};
 use borrow_check::nll::region_infer::values::ToElementIndex;
 use borrow_check::nll::type_check::Locations;
 use rustc::hir::def_id::DefId;
@@ -259,15 +259,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         }
     }
 
-    crate fn why_region_contains_point(&self, fr1: RegionVid, elem: Location) -> Option<Cause> {
-        // Find some constraint `X: Y` where:
-        // - `fr1: X` transitively
-        // - and `Y` is live at `elem`
+    // Find some constraint `X: Y` where:
+    // - `fr1: X` transitively
+    // - and `Y` is live at `elem`
+    crate fn find_constraint(&self, fr1: RegionVid, elem: Location) -> RegionVid {
         let index = self.blame_constraint(fr1, elem);
-        let region_sub = self.constraints[index].sub;
-
-        // then return why `Y` was live at `elem`
-        self.liveness_constraints.cause(region_sub, elem)
+        self.constraints[index].sub
     }
 
     /// Tries to finds a good span to blame for the fact that `fr1`
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index 014b37a0a27..fd6d79d160e 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -75,8 +75,6 @@ pub struct RegionInferenceContext<'tcx> {
     universal_regions: UniversalRegions<'tcx>,
 }
 
-struct TrackCauses(bool);
-
 struct RegionDefinition<'tcx> {
     /// Why we created this variable. Mostly these will be
     /// `RegionVariableOrigin::NLL`, but some variables get created
@@ -105,13 +103,6 @@ pub(crate) enum Cause {
 
     /// point inserted because Local was dropped at the given Location
     DropVar(Local, Location),
-
-    /// point inserted because the type was live at the given Location,
-    /// but not as part of some local variable
-    LiveOther(Location),
-
-    /// part of the initial set of values for a universally quantified region
-    UniversalRegion(RegionVid),
 }
 
 /// A "type test" corresponds to an outlives constraint between a type
@@ -283,7 +274,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 self.liveness_constraints.add_element(
                     variable,
                     point_index,
-                    &Cause::UniversalRegion(variable),
                 );
             }
 
@@ -291,7 +281,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             self.liveness_constraints.add_element(
                 variable,
                 variable,
-                &Cause::UniversalRegion(variable),
             );
         }
     }
@@ -337,13 +326,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ///
     /// Returns `true` if this constraint is new and `false` is the
     /// constraint was already present.
-    pub(super) fn add_live_point(&mut self, v: RegionVid, point: Location, cause: &Cause) -> bool {
+    pub(super) fn add_live_point(&mut self, v: RegionVid, point: Location) -> bool {
         debug!("add_live_point({:?}, {:?})", v, point);
         assert!(self.inferred_values.is_none(), "values already inferred");
-        debug!("add_live_point: @{:?} Adding cause {:?}", point, cause);
 
         let element = self.elements.index(point);
-        self.liveness_constraints.add_element(v, element, &cause)
+        self.liveness_constraints.add_element(v, element)
     }
 
     /// Indicates that the region variable `sup` must outlive `sub` is live at the point `point`.
@@ -436,7 +424,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         // The initial values for each region are derived from the liveness
         // constraints we have accumulated.
-        let mut inferred_values = self.liveness_constraints.duplicate(TrackCauses(false));
+        let mut inferred_values = self.liveness_constraints.clone();
 
         let dependency_map = self.dependency_map.as_ref().unwrap();
 
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs
index e914be52db0..5be4297f660 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs
@@ -8,18 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use borrow_check::nll::region_infer::TrackCauses;
 use rustc::mir::{BasicBlock, Location, Mir};
 use rustc::ty::RegionVid;
 use rustc_data_structures::bitvec::SparseBitMatrix;
-use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::indexed_vec::IndexVec;
 use std::fmt::Debug;
 use std::rc::Rc;
 
-use super::Cause;
-
 /// Maps between the various kinds of elements of a region value to
 /// the internal indices that w use.
 pub(super) struct RegionValueElements {
@@ -180,19 +176,12 @@ impl ToElementIndex for RegionElementIndex {
 /// compact `SparseBitMatrix` representation, with one row per region
 /// variable. The columns consist of either universal regions or
 /// points in the CFG.
+#[derive(Clone)]
 pub(super) struct RegionValues {
     elements: Rc<RegionValueElements>,
     matrix: SparseBitMatrix<RegionVid, RegionElementIndex>,
-
-    /// If cause tracking is enabled, maps from a pair (r, e)
-    /// consisting of a region `r` that contains some element `e` to
-    /// the reason that the element is contained. There should be an
-    /// entry for every bit set to 1 in `SparseBitMatrix`.
-    causes: Option<CauseMap>,
 }
 
-type CauseMap = FxHashMap<(RegionVid, RegionElementIndex), Cause>;
-
 impl RegionValues {
     /// Creates a new set of "region values" that tracks causal information.
     /// Each of the regions in num_region_variables will be initialized with an
@@ -209,25 +198,6 @@ impl RegionValues {
                 RegionVid::new(num_region_variables),
                 RegionElementIndex::new(elements.num_elements()),
             ),
-            causes: Some(CauseMap::default()),
-        }
-    }
-
-    /// Duplicates the region values. If track_causes is false, then the
-    /// resulting value will not track causal information (and any existing
-    /// causal information is dropped). Otherwise, the causal information is
-    /// preserved and maintained. Tracking the causal information makes region
-    /// propagation significantly slower, so we prefer not to do it until an
-    /// error is reported.
-    pub(super) fn duplicate(&self, track_causes: TrackCauses) -> Self {
-        Self {
-            elements: self.elements.clone(),
-            matrix: self.matrix.clone(),
-            causes: if track_causes.0 {
-                self.causes.clone()
-            } else {
-                None
-            },
         }
     }
 
@@ -237,10 +207,10 @@ impl RegionValues {
         &mut self,
         r: RegionVid,
         elem: E,
-        cause: &Cause,
     ) -> bool {
         let i = self.elements.index(elem);
-        self.add_internal(r, i, |_| cause.clone())
+        debug!("add(r={:?}, elem={:?})", r, elem);
+        self.matrix.add(r, i)
     }
 
     /// Add all elements in `r_from` to `r_to` (because e.g. `r_to:
@@ -249,40 +219,6 @@ impl RegionValues {
         self.matrix.merge(r_from, r_to)
     }
 
-    /// Internal method to add an element to a region.
-    ///
-    /// Takes a "lazy" cause -- this function will return the cause, but it will only
-    /// be invoked if cause tracking is enabled.
-    fn add_internal<F>(&mut self, r: RegionVid, i: RegionElementIndex, make_cause: F) -> bool
-    where
-        F: FnOnce(&CauseMap) -> Cause,
-    {
-        if self.matrix.add(r, i) {
-            debug!("add(r={:?}, i={:?})", r, self.elements.to_element(i));
-
-            if let Some(causes) = &mut self.causes {
-                let cause = make_cause(causes);
-                causes.insert((r, i), cause);
-            }
-
-            true
-        } else {
-            if let Some(causes) = &mut self.causes {
-                let cause = make_cause(causes);
-                let old_cause = causes.get_mut(&(r, i)).unwrap();
-                // #49998: compare using root cause alone to avoid
-                // useless traffic from similar outlives chains.
-
-                if cause < *old_cause {
-                    *old_cause = cause;
-                    return true;
-                }
-            }
-
-            false
-        }
-    }
-
     /// True if the region `r` contains the given element.
     pub(super) fn contains<E: ToElementIndex>(&self, r: RegionVid, elem: E) -> bool {
         let i = self.elements.index(elem);
@@ -398,18 +334,4 @@ impl RegionValues {
             ));
         }
     }
-
-    /// Given a region `r` that contains the element `elem`, returns the `Cause`
-    /// that tells us *why* `elem` is found in that region.
-    ///
-    /// Returns None if cause tracking is disabled or `elem` is not
-    /// actually found in `r`.
-    pub(super) fn cause<T: ToElementIndex>(&self, r: RegionVid, elem: T) -> Option<Cause> {
-        let index = self.elements.index(elem);
-        if let Some(causes) = &self.causes {
-            causes.get(&(r, index)).cloned()
-        } else {
-            None
-        }
-    }
 }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs
index d84dcc56782..dbdfef21970 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use borrow_check::nll::region_infer::Cause;
 use borrow_check::nll::type_check::AtLocation;
 use dataflow::move_paths::{HasMoveData, MoveData};
 use dataflow::MaybeInitializedPlaces;
@@ -88,8 +87,7 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
             .simulate_block(self.mir, bb, |location, live_locals| {
                 for live_local in live_locals.iter() {
                     let live_local_ty = self.mir.local_decls[live_local].ty;
-                    let cause = Cause::LiveVar(live_local, location);
-                    Self::push_type_live_constraint(&mut self.cx, live_local_ty, location, cause);
+                    Self::push_type_live_constraint(&mut self.cx, live_local_ty, location);
                 }
             });
 
@@ -161,7 +159,6 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
         cx: &mut TypeChecker<'_, 'gcx, 'tcx>,
         value: T,
         location: Location,
-        cause: Cause,
     ) where
         T: TypeFoldable<'tcx>,
     {
@@ -173,7 +170,7 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
         cx.tcx().for_each_free_region(&value, |live_region| {
             cx.constraints
                 .liveness_set
-                .push((live_region, location, cause.clone()));
+                .push((live_region, location));
         });
     }
 
@@ -210,9 +207,8 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
 
         // All things in the `outlives` array may be touched by
         // the destructor and must be live at this point.
-        let cause = Cause::DropVar(dropped_local, location);
         for &kind in &drop_data.dropck_result.kinds {
-            Self::push_type_live_constraint(&mut self.cx, kind, location, cause);
+            Self::push_type_live_constraint(&mut self.cx, kind, location);
         }
     }
 
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 e3d20d9a8db..d5cf55c0f77 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -14,7 +14,6 @@
 use borrow_check::location::LocationTable;
 use borrow_check::nll::constraint_set::ConstraintSet;
 use borrow_check::nll::facts::AllFacts;
-use borrow_check::nll::region_infer::Cause;
 use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest};
 use borrow_check::nll::universal_regions::UniversalRegions;
 use dataflow::move_paths::MoveData;
@@ -615,7 +614,7 @@ crate struct MirTypeckRegionConstraints<'tcx> {
     /// not otherwise appear in the MIR -- in particular, the
     /// late-bound regions that it instantiates at call-sites -- and
     /// hence it must report on their liveness constraints.
-    crate liveness_set: Vec<(ty::Region<'tcx>, Location, Cause)>,
+    crate liveness_set: Vec<(ty::Region<'tcx>, Location)>,
 
     crate outlives_constraints: ConstraintSet,
 
@@ -986,7 +985,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     self.constraints.liveness_set.push((
                         late_bound_region,
                         term_location,
-                        Cause::LiveOther(term_location),
                     ));
                 }
 
diff --git a/src/test/ui/generator/borrowing.nll.stderr b/src/test/ui/generator/borrowing.nll.stderr
index 243e9018585..015538b16f9 100644
--- a/src/test/ui/generator/borrowing.nll.stderr
+++ b/src/test/ui/generator/borrowing.nll.stderr
@@ -2,15 +2,10 @@ error[E0597]: `a` does not live long enough
   --> $DIR/borrowing.rs:18:18
    |
 LL |         unsafe { (|| yield &a).resume() }
-   |                  ^^^^^^^^^^^^^
-   |                  |
-   |                  borrowed value does not live long enough
-   |                  borrow may end up in a temporary, created here
+   |                  ^^^^^^^^^^^^^ borrowed value does not live long enough
 LL |         //~^ ERROR: `a` does not live long enough
 LL |     };
-   |     -- temporary later dropped here, potentially using the reference
-   |     |
-   |     borrowed value only lives until here
+   |     - borrowed value only lives until here
 
 error[E0597]: `a` does not live long enough
   --> $DIR/borrowing.rs:24:9
diff --git a/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr b/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr
index 70870b98365..08839c23c37 100644
--- a/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr
+++ b/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr
@@ -1,19 +1,11 @@
 error[E0597]: `b` does not live long enough
   --> $DIR/ref-escapes-but-not-over-yield.rs:24:13
    |
-LL |       let mut b = move || {
-   |  _________________-
-LL | |         yield();
-LL | |         let b = 5;
-LL | |         a = &b;
-   | |             ^^ borrowed value does not live long enough
-LL | |         //~^ ERROR `b` does not live long enough
-LL | |     };
-   | |     -
-   | |     |
-   | |     borrowed value only lives until here
-   | |_____temporary later dropped here, potentially using the reference
-   |       borrow may end up in a temporary, created here
+LL |         a = &b;
+   |             ^^ borrowed value does not live long enough
+LL |         //~^ ERROR `b` does not live long enough
+LL |     };
+   |     - borrowed value only lives until here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issue-47646.stderr b/src/test/ui/issue-47646.stderr
index b1289146e0e..4bdce85d18b 100644
--- a/src/test/ui/issue-47646.stderr
+++ b/src/test/ui/issue-47646.stderr
@@ -3,15 +3,9 @@ error[E0502]: cannot borrow `heap` as immutable because it is also borrowed as m
    |
 LL |     let borrow = heap.peek_mut();
    |                  ---- mutable borrow occurs here
-LL | 
-LL |     match (borrow, ()) {
-   |           ------------ borrow may end up in a temporary, created here
-LL |         (Some(_), ()) => {
+...
 LL |             println!("{:?}", heap); //~ ERROR cannot borrow `heap` as immutable
    |                              ^^^^ immutable borrow occurs here
-...
-LL |     };
-   |      - temporary later dropped here, potentially using the reference
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/span/destructor-restrictions.nll.stderr b/src/test/ui/span/destructor-restrictions.nll.stderr
index 5de246cbb73..8be4cf445da 100644
--- a/src/test/ui/span/destructor-restrictions.nll.stderr
+++ b/src/test/ui/span/destructor-restrictions.nll.stderr
@@ -2,14 +2,9 @@ error[E0597]: `*a` does not live long enough
   --> $DIR/destructor-restrictions.rs:18:10
    |
 LL |         *a.borrow() + 1
-   |          ^---------
-   |          |
-   |          borrowed value does not live long enough
-   |          borrow may end up in a temporary, created here
+   |          ^ borrowed value does not live long enough
 LL |     }; //~^ ERROR `*a` does not live long enough
-   |     -- temporary later dropped here, potentially using the reference
-   |     |
-   |     borrowed value only lives until here
+   |     - borrowed value only lives until here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr
index 56f2d14390e..ec2f5a25631 100644
--- a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr
+++ b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr
@@ -2,28 +2,17 @@ error[E0597]: `y` does not live long enough
   --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:20:5
    |
 LL |     y.borrow().clone()
-   |     ^---------
-   |     |
-   |     borrowed value does not live long enough
-   |     borrow may end up in a temporary, created here
+   |     ^ borrowed value does not live long enough
 LL | }
-   | -
-   | |
-   | borrowed value only lives until here
-   | temporary later dropped here, potentially using the reference
+   | - borrowed value only lives until here
 
 error[E0597]: `y` does not live long enough
   --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:27:9
    |
 LL |         y.borrow().clone()
-   |         ^---------
-   |         |
-   |         borrowed value does not live long enough
-   |         borrow may end up in a temporary, created here
+   |         ^ borrowed value does not live long enough
 LL |     };
-   |     -- temporary later dropped here, potentially using the reference
-   |     |
-   |     borrowed value only lives until here
+   |     - borrowed value only lives until here
 
 error: aborting due to 2 previous errors