about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-12-30 14:47:26 +0000
committerbors <bors@rust-lang.org>2019-12-30 14:47:26 +0000
commit9d6f87184e5116cf4a96f6686eb67994f19908a5 (patch)
treeba1a33ab4e00e6856d9738cfaeaae0e8aded4db1
parent0fb43801368ae8b5931583f813071120bed55c35 (diff)
parent96ce6076c35b5c9c06f13cb571b210e08160641c (diff)
downloadrust-9d6f87184e5116cf4a96f6686eb67994f19908a5.tar.gz
rust-9d6f87184e5116cf4a96f6686eb67994f19908a5.zip
Auto merge of #67474 - mark-i-m:simplify-borrow_check-4, r=matthewjasper
Get rid of ErrorReportingCtx [5/N]

We can now use `MirBorrowckCtxt` instead :)

```
6 files changed, 122 insertions(+), 243 deletions(-)
```

This is a followup to (and thus blocked on) #67241.

r? @matthewjasper

cc @eddyb

I while try to do one more to get rid of the weird usage of `RegionInferenceCtx` in `borrow_check::diagnostics::{region_errors, region_naming}`. I think those uses can possibly also be refactored to use `MirBorrowckCtxt`...
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs13
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/mod.rs2
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs85
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/region_errors.rs113
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/region_name.rs128
-rw-r--r--src/librustc_mir/borrow_check/mod.rs17
6 files changed, 119 insertions, 239 deletions
diff --git a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
index 04f025fcbea..3b7aac5c7f9 100644
--- a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
@@ -289,16 +289,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
             None => {
                 if let Some(region) = regioncx.to_error_region_vid(borrow_region_vid) {
-                    let (category, from_closure, span, region_name) =
-                        self.nonlexical_regioncx.free_region_constraint_info(
-                            &self.body,
-                            &self.local_names,
-                            &self.upvars,
-                            self.mir_def_id,
-                            self.infcx,
-                            borrow_region_vid,
-                            region,
-                        );
+                    let (category, from_closure, span, region_name) = self
+                        .nonlexical_regioncx
+                        .free_region_constraint_info(self, borrow_region_vid, region);
                     if let Some(region_name) = region_name {
                         let opt_place_desc = self.describe_place(borrow.borrowed_place.as_ref());
                         BorrowExplanation::MustBeValidFor {
diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs
index cd2138fdf94..5272054346e 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mod.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs
@@ -32,7 +32,7 @@ mod region_errors;
 
 crate use mutability_errors::AccessKind;
 crate use outlives_suggestion::OutlivesSuggestionBuilder;
-crate use region_errors::{ErrorConstraintInfo, ErrorReportingCtx, RegionErrorKind, RegionErrors};
+crate use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
 crate use region_name::{RegionErrorNamingCtx, RegionName, RegionNameSource};
 
 pub(super) struct IncludingDowncast(pub(super) bool);
diff --git a/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs b/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
index 8acb2feeb70..1425c22e461 100644
--- a/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
@@ -4,20 +4,15 @@
 use std::collections::BTreeMap;
 
 use log::debug;
-use rustc::mir::{Body, Local};
-use rustc::{hir::def_id::DefId, infer::InferCtxt, ty::RegionVid};
+use rustc::ty::RegionVid;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{Diagnostic, DiagnosticBuilder};
-use rustc_index::vec::IndexVec;
-use syntax_pos::symbol::Symbol;
+use rustc_errors::DiagnosticBuilder;
 
 use smallvec::SmallVec;
 
-use crate::borrow_check::region_infer::RegionInferenceContext;
+use crate::borrow_check::MirBorrowckCtxt;
 
-use super::{
-    ErrorConstraintInfo, ErrorReportingCtx, RegionErrorNamingCtx, RegionName, RegionNameSource,
-};
+use super::{ErrorConstraintInfo, RegionErrorNamingCtx, RegionName, RegionNameSource};
 
 /// The different things we could suggest.
 enum SuggestedConstraint {
@@ -35,12 +30,8 @@ enum SuggestedConstraint {
 /// corresponding to a function definition.
 ///
 /// Adds a help note suggesting adding a where clause with the needed constraints.
-pub struct OutlivesSuggestionBuilder<'a> {
-    /// The MIR DefId of the fn with the lifetime error.
-    mir_def_id: DefId,
-
-    local_names: &'a IndexVec<Local, Option<Symbol>>,
-
+#[derive(Default)]
+pub struct OutlivesSuggestionBuilder {
     /// The list of outlives constraints that need to be added. Specifically, we map each free
     /// region to all other regions that it must outlive. I will use the shorthand `fr:
     /// outlived_frs`. Not all of these regions will already have names necessarily. Some could be
@@ -49,16 +40,7 @@ pub struct OutlivesSuggestionBuilder<'a> {
     constraints_to_add: BTreeMap<RegionVid, Vec<RegionVid>>,
 }
 
-impl OutlivesSuggestionBuilder<'a> {
-    /// Create a new builder for the given MIR node representing a fn definition.
-    crate fn new(mir_def_id: DefId, local_names: &'a IndexVec<Local, Option<Symbol>>) -> Self {
-        OutlivesSuggestionBuilder {
-            mir_def_id,
-            local_names,
-            constraints_to_add: BTreeMap::default(),
-        }
-    }
-
+impl OutlivesSuggestionBuilder {
     /// Returns `true` iff the `RegionNameSource` is a valid source for an outlives
     /// suggestion.
     //
@@ -94,22 +76,19 @@ impl OutlivesSuggestionBuilder<'a> {
     /// Returns a name for the region if it is suggestable. See `region_name_is_suggestable`.
     fn region_vid_to_name(
         &self,
-        errctx: &ErrorReportingCtx<'_, '_, '_>,
+        mbcx: &MirBorrowckCtxt<'_, '_>,
         renctx: &mut RegionErrorNamingCtx,
         region: RegionVid,
     ) -> Option<RegionName> {
-        errctx
-            .region_infcx
-            .give_region_a_name(errctx, renctx, region)
+        mbcx.nonlexical_regioncx
+            .give_region_a_name(mbcx, renctx, region)
             .filter(Self::region_name_is_suggestable)
     }
 
     /// Compiles a list of all suggestions to be printed in the final big suggestion.
-    fn compile_all_suggestions<'tcx>(
+    fn compile_all_suggestions(
         &self,
-        body: &Body<'tcx>,
-        region_infcx: &RegionInferenceContext<'tcx>,
-        infcx: &InferCtxt<'_, 'tcx>,
+        mbcx: &MirBorrowckCtxt<'_, '_>,
         renctx: &mut RegionErrorNamingCtx,
     ) -> SmallVec<[SuggestedConstraint; 2]> {
         let mut suggested = SmallVec::new();
@@ -118,20 +97,8 @@ impl OutlivesSuggestionBuilder<'a> {
         // out silly duplicate messages.
         let mut unified_already = FxHashSet::default();
 
-        let errctx = ErrorReportingCtx {
-            region_infcx,
-            infcx,
-            body,
-            mir_def_id: self.mir_def_id,
-            local_names: self.local_names,
-
-            // We should not be suggesting naming upvars, so we pass in a dummy set of upvars that
-            // should never be used.
-            upvars: &[],
-        };
-
         for (fr, outlived) in &self.constraints_to_add {
-            let fr_name = if let Some(fr_name) = self.region_vid_to_name(&errctx, renctx, *fr) {
+            let fr_name = if let Some(fr_name) = self.region_vid_to_name(mbcx, renctx, *fr) {
                 fr_name
             } else {
                 continue;
@@ -141,7 +108,7 @@ impl OutlivesSuggestionBuilder<'a> {
                 .iter()
                 // if there is a `None`, we will just omit that constraint
                 .filter_map(|fr| {
-                    self.region_vid_to_name(&errctx, renctx, *fr).map(|rname| (fr, rname))
+                    self.region_vid_to_name(mbcx, renctx, *fr).map(|rname| (fr, rname))
                 })
                 .collect::<Vec<_>>();
 
@@ -204,14 +171,14 @@ impl OutlivesSuggestionBuilder<'a> {
     /// suggestable.
     crate fn intermediate_suggestion(
         &mut self,
-        errctx: &ErrorReportingCtx<'_, '_, '_>,
+        mbcx: &MirBorrowckCtxt<'_, '_>,
         errci: &ErrorConstraintInfo,
         renctx: &mut RegionErrorNamingCtx,
         diag: &mut DiagnosticBuilder<'_>,
     ) {
         // Emit an intermediate note.
-        let fr_name = self.region_vid_to_name(errctx, renctx, errci.fr);
-        let outlived_fr_name = self.region_vid_to_name(errctx, renctx, errci.outlived_fr);
+        let fr_name = self.region_vid_to_name(mbcx, renctx, errci.fr);
+        let outlived_fr_name = self.region_vid_to_name(mbcx, renctx, errci.outlived_fr);
 
         if let (Some(fr_name), Some(outlived_fr_name)) = (fr_name, outlived_fr_name) {
             if let RegionNameSource::Static = outlived_fr_name.source {
@@ -227,12 +194,9 @@ impl OutlivesSuggestionBuilder<'a> {
 
     /// If there is a suggestion to emit, add a diagnostic to the buffer. This is the final
     /// suggestion including all collected constraints.
-    crate fn add_suggestion<'tcx>(
+    crate fn add_suggestion(
         &self,
-        body: &Body<'tcx>,
-        region_infcx: &RegionInferenceContext<'tcx>,
-        infcx: &InferCtxt<'_, 'tcx>,
-        errors_buffer: &mut Vec<Diagnostic>,
+        mbcx: &mut MirBorrowckCtxt<'_, '_>,
         renctx: &mut RegionErrorNamingCtx,
     ) {
         // No constraints to add? Done.
@@ -251,7 +215,7 @@ impl OutlivesSuggestionBuilder<'a> {
         }
 
         // Get all suggestable constraints.
-        let suggested = self.compile_all_suggestions(body, region_infcx, infcx, renctx);
+        let suggested = self.compile_all_suggestions(mbcx, renctx);
 
         // If there are no suggestable constraints...
         if suggested.is_empty() {
@@ -262,7 +226,7 @@ impl OutlivesSuggestionBuilder<'a> {
         // If there is exactly one suggestable constraints, then just suggest it. Otherwise, emit a
         // list of diagnostics.
         let mut diag = if suggested.len() == 1 {
-            infcx.tcx.sess.diagnostic().struct_help(&match suggested.last().unwrap() {
+            mbcx.infcx.tcx.sess.diagnostic().struct_help(&match suggested.last().unwrap() {
                 SuggestedConstraint::Outlives(a, bs) => {
                     let bs: SmallVec<[String; 2]> = bs.iter().map(|r| format!("{}", r)).collect();
                     format!("add bound `{}: {}`", a, bs.join(" + "))
@@ -275,7 +239,8 @@ impl OutlivesSuggestionBuilder<'a> {
             })
         } else {
             // Create a new diagnostic.
-            let mut diag = infcx
+            let mut diag = mbcx
+                .infcx
                 .tcx
                 .sess
                 .diagnostic()
@@ -305,10 +270,10 @@ impl OutlivesSuggestionBuilder<'a> {
         };
 
         // We want this message to appear after other messages on the mir def.
-        let mir_span = infcx.tcx.def_span(self.mir_def_id);
+        let mir_span = mbcx.infcx.tcx.def_span(mbcx.mir_def_id);
         diag.sort_span = mir_span.shrink_to_hi();
 
         // Buffer the diagnostic
-        diag.buffer(errors_buffer);
+        diag.buffer(&mut mbcx.errors_buffer);
     }
 }
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
index e6158133628..d560f7c5175 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
@@ -5,14 +5,13 @@ use rustc::infer::{
     error_reporting::nice_region_error::NiceRegionError, region_constraints::GenericKind,
     InferCtxt, NLLRegionVariableOrigin,
 };
-use rustc::mir::{Body, ConstraintCategory, Local, Location};
+use rustc::mir::{Body, ConstraintCategory, Location};
 use rustc::ty::{self, RegionVid, Ty};
 use rustc_errors::DiagnosticBuilder;
 use rustc_index::vec::IndexVec;
 use std::collections::VecDeque;
 use syntax::errors::Applicability;
 use syntax::symbol::kw;
-use syntax_pos::symbol::Symbol;
 use syntax_pos::Span;
 
 use crate::util::borrowck_errors;
@@ -20,7 +19,7 @@ use crate::util::borrowck_errors;
 use crate::borrow_check::{
     constraints::OutlivesConstraint, nll::ConstraintDescription,
     region_infer::RegionInferenceContext, type_check::Locations, universal_regions::DefiningTy,
-    Upvar,
+    MirBorrowckCtxt,
 };
 
 use super::{OutlivesSuggestionBuilder, RegionErrorNamingCtx, RegionName, RegionNameSource};
@@ -116,27 +115,6 @@ crate enum RegionErrorKind<'tcx> {
     },
 }
 
-/// Various pieces of state used when reporting borrow checker errors.
-pub struct ErrorReportingCtx<'a, 'b, 'tcx> {
-    /// The region inference context used for borrow chekcing this MIR body.
-    pub(super) region_infcx: &'b RegionInferenceContext<'tcx>,
-
-    /// The inference context used for type checking.
-    pub(super) infcx: &'b InferCtxt<'a, 'tcx>,
-
-    /// The MIR def we are reporting errors on.
-    pub(super) mir_def_id: DefId,
-
-    /// The MIR body we are reporting errors on (for convenience).
-    pub(super) body: &'b Body<'tcx>,
-
-    /// User variable names for MIR locals (where applicable).
-    pub(super) local_names: &'b IndexVec<Local, Option<Symbol>>,
-
-    /// Any upvars for the MIR body we have kept track of during borrow checking.
-    pub(super) upvars: &'b [Upvar],
-}
-
 /// Information about the various region constraints involved in a borrow checker error.
 #[derive(Clone, Debug)]
 pub struct ErrorConstraintInfo {
@@ -454,28 +432,24 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
     pub(in crate::borrow_check) fn report_error<'a>(
         &'a self,
-        body: &Body<'tcx>,
-        local_names: &IndexVec<Local, Option<Symbol>>,
-        upvars: &[Upvar],
-        infcx: &'a InferCtxt<'a, 'tcx>,
-        mir_def_id: DefId,
+        mbcx: &MirBorrowckCtxt<'a, 'tcx>,
         fr: RegionVid,
         fr_origin: NLLRegionVariableOrigin,
         outlived_fr: RegionVid,
-        outlives_suggestion: &mut OutlivesSuggestionBuilder<'_>,
+        outlives_suggestion: &mut OutlivesSuggestionBuilder,
         renctx: &mut RegionErrorNamingCtx,
     ) -> DiagnosticBuilder<'a> {
         debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
 
-        let (category, _, span) = self.best_blame_constraint(body, fr, fr_origin, |r| {
+        let (category, _, span) = self.best_blame_constraint(&mbcx.body, fr, fr_origin, |r| {
             self.provides_universal_region(r, fr, outlived_fr)
         });
 
         debug!("report_error: category={:?} {:?}", category, span);
         // Check if we can use one of the "nice region errors".
         if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
-            let tables = infcx.tcx.typeck_tables_of(mir_def_id);
-            let nice = NiceRegionError::new_from_span(infcx, span, o, f, Some(tables));
+            let tables = mbcx.infcx.tcx.typeck_tables_of(mbcx.mir_def_id);
+            let nice = NiceRegionError::new_from_span(mbcx.infcx, span, o, f, Some(tables));
             if let Some(diag) = nice.try_report_from_nll() {
                 return diag;
             }
@@ -491,9 +465,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             fr_is_local, outlived_fr_is_local, category
         );
 
-        let errctx =
-            ErrorReportingCtx { region_infcx: self, infcx, mir_def_id, body, local_names, upvars };
-
         let errci = ErrorConstraintInfo {
             fr,
             outlived_fr,
@@ -504,22 +475,22 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         };
 
         match (category, fr_is_local, outlived_fr_is_local) {
-            (ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(infcx, fr) => {
-                self.report_fnmut_error(&errctx, &errci, renctx)
+            (ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(mbcx.infcx, fr) => {
+                self.report_fnmut_error(mbcx, &errci, renctx)
             }
             (ConstraintCategory::Assignment, true, false)
             | (ConstraintCategory::CallArgument, true, false) => {
-                let mut db = self.report_escaping_data_error(&errctx, &errci, renctx);
+                let mut db = self.report_escaping_data_error(mbcx, &errci, renctx);
 
-                outlives_suggestion.intermediate_suggestion(&errctx, &errci, renctx, &mut db);
+                outlives_suggestion.intermediate_suggestion(mbcx, &errci, renctx, &mut db);
                 outlives_suggestion.collect_constraint(fr, outlived_fr);
 
                 db
             }
             _ => {
-                let mut db = self.report_general_error(&errctx, &errci, renctx);
+                let mut db = self.report_general_error(mbcx, &errci, renctx);
 
-                outlives_suggestion.intermediate_suggestion(&errctx, &errci, renctx, &mut db);
+                outlives_suggestion.intermediate_suggestion(mbcx, &errci, renctx, &mut db);
                 outlives_suggestion.collect_constraint(fr, outlived_fr);
 
                 db
@@ -569,13 +540,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// ```
     fn report_fnmut_error(
         &self,
-        errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
+        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         errci: &ErrorConstraintInfo,
         renctx: &mut RegionErrorNamingCtx,
     ) -> DiagnosticBuilder<'_> {
         let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
 
-        let mut diag = errctx
+        let mut diag = mbcx
             .infcx
             .tcx
             .sess
@@ -593,7 +564,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         diag.span_label(*span, message);
 
-        match self.give_region_a_name(errctx, renctx, *outlived_fr).unwrap().source {
+        match self.give_region_a_name(mbcx, renctx, *outlived_fr).unwrap().source {
             RegionNameSource::NamedEarlyBoundRegion(fr_span)
             | RegionNameSource::NamedFreeRegion(fr_span)
             | RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _)
@@ -630,21 +601,24 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// ```
     fn report_escaping_data_error(
         &self,
-        errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
+        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         errci: &ErrorConstraintInfo,
         renctx: &mut RegionErrorNamingCtx,
     ) -> DiagnosticBuilder<'_> {
-        let ErrorReportingCtx { infcx, body, upvars, local_names, .. } = errctx;
-
         let ErrorConstraintInfo { span, category, .. } = errci;
 
-        let fr_name_and_span =
-            self.get_var_name_and_span_for_region(infcx.tcx, body, local_names, upvars, errci.fr);
+        let fr_name_and_span = self.get_var_name_and_span_for_region(
+            mbcx.infcx.tcx,
+            &mbcx.body,
+            &mbcx.local_names,
+            &mbcx.upvars,
+            errci.fr,
+        );
         let outlived_fr_name_and_span = self.get_var_name_and_span_for_region(
-            infcx.tcx,
-            body,
-            local_names,
-            upvars,
+            mbcx.infcx.tcx,
+            &mbcx.body,
+            &mbcx.local_names,
+            &mbcx.upvars,
             errci.outlived_fr,
         );
 
@@ -662,14 +636,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             || escapes_from == "const"
         {
             return self.report_general_error(
-                errctx,
+                mbcx,
                 &ErrorConstraintInfo { fr_is_local: true, outlived_fr_is_local: false, ..*errci },
                 renctx,
             );
         }
 
         let mut diag =
-            borrowck_errors::borrowed_data_escapes_closure(infcx.tcx, *span, escapes_from);
+            borrowck_errors::borrowed_data_escapes_closure(mbcx.infcx.tcx, *span, escapes_from);
 
         if let Some((Some(outlived_fr_name), outlived_fr_span)) = outlived_fr_name_and_span {
             diag.span_label(
@@ -713,11 +687,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// ```
     fn report_general_error(
         &self,
-        errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
+        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         errci: &ErrorConstraintInfo,
         renctx: &mut RegionErrorNamingCtx,
     ) -> DiagnosticBuilder<'_> {
-        let ErrorReportingCtx { infcx, mir_def_id, .. } = errctx;
         let ErrorConstraintInfo {
             fr,
             fr_is_local,
@@ -728,13 +701,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             ..
         } = errci;
 
-        let mut diag = infcx.tcx.sess.struct_span_err(*span, "lifetime may not live long enough");
+        let mut diag =
+            mbcx.infcx.tcx.sess.struct_span_err(*span, "lifetime may not live long enough");
 
-        let mir_def_name = if infcx.tcx.is_closure(*mir_def_id) { "closure" } else { "function" };
+        let mir_def_name =
+            if mbcx.infcx.tcx.is_closure(mbcx.mir_def_id) { "closure" } else { "function" };
 
-        let fr_name = self.give_region_a_name(errctx, renctx, *fr).unwrap();
+        let fr_name = self.give_region_a_name(mbcx, renctx, *fr).unwrap();
         fr_name.highlight_region_name(&mut diag);
-        let outlived_fr_name = self.give_region_a_name(errctx, renctx, *outlived_fr).unwrap();
+        let outlived_fr_name = self.give_region_a_name(mbcx, renctx, *outlived_fr).unwrap();
         outlived_fr_name.highlight_region_name(&mut diag);
 
         match (category, outlived_fr_is_local, fr_is_local) {
@@ -761,7 +736,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             }
         }
 
-        self.add_static_impl_trait_suggestion(infcx, &mut diag, *fr, fr_name, *outlived_fr);
+        self.add_static_impl_trait_suggestion(mbcx.infcx, &mut diag, *fr, fr_name, *outlived_fr);
 
         diag
     }
@@ -854,25 +829,19 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
     crate fn free_region_constraint_info(
         &self,
-        body: &Body<'tcx>,
-        local_names: &IndexVec<Local, Option<Symbol>>,
-        upvars: &[Upvar],
-        mir_def_id: DefId,
-        infcx: &InferCtxt<'_, 'tcx>,
+        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         borrow_region: RegionVid,
         outlived_region: RegionVid,
     ) -> (ConstraintCategory, bool, Span, Option<RegionName>) {
         let (category, from_closure, span) = self.best_blame_constraint(
-            body,
+            &mbcx.body,
             borrow_region,
             NLLRegionVariableOrigin::FreeRegion,
             |r| self.provides_universal_region(r, borrow_region, outlived_region),
         );
 
         let mut renctx = RegionErrorNamingCtx::new();
-        let errctx =
-            ErrorReportingCtx { infcx, body, local_names, upvars, mir_def_id, region_infcx: self };
-        let outlived_fr_name = self.give_region_a_name(&errctx, &mut renctx, outlived_region);
+        let outlived_fr_name = self.give_region_a_name(mbcx, &mut renctx, outlived_region);
 
         (category, from_closure, span, outlived_fr_name)
     }
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_name.rs b/src/librustc_mir/borrow_check/diagnostics/region_name.rs
index 37e2b68692d..2c480b8e9dc 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_name.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_name.rs
@@ -2,21 +2,17 @@ use std::fmt::{self, Display};
 
 use rustc::hir;
 use rustc::hir::def::{DefKind, Res};
-use rustc::hir::def_id::DefId;
-use rustc::infer::InferCtxt;
-use rustc::mir::{Body, Local};
 use rustc::ty::print::RegionHighlightMode;
 use rustc::ty::subst::{GenericArgKind, SubstsRef};
 use rustc::ty::{self, RegionVid, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::DiagnosticBuilder;
-use rustc_index::vec::IndexVec;
 use syntax::symbol::kw;
 use syntax_pos::{symbol::Symbol, Span, DUMMY_SP};
 
 use crate::borrow_check::{
-    diagnostics::region_errors::ErrorReportingCtx, nll::ToRegionVid,
-    region_infer::RegionInferenceContext, universal_regions::DefiningTy, Upvar,
+    nll::ToRegionVid, region_infer::RegionInferenceContext, universal_regions::DefiningTy,
+    MirBorrowckCtxt,
 };
 
 /// A name for a particular region used in emitting diagnostics. This name could be a generated
@@ -193,12 +189,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// and then return the name `'1` for us to use.
     crate fn give_region_a_name(
         &self,
-        errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
+        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         renctx: &mut RegionErrorNamingCtx,
         fr: RegionVid,
     ) -> Option<RegionName> {
-        let ErrorReportingCtx { infcx, body, mir_def_id, local_names, upvars, .. } = errctx;
-
         debug!("give_region_a_name(fr={:?}, counter={:?})", fr, renctx.counter);
 
         assert!(self.universal_regions.is_universal_region(fr));
@@ -208,38 +202,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         }
 
         let value = self
-            .give_name_from_error_region(infcx.tcx, *mir_def_id, fr, renctx)
-            .or_else(|| {
-                self.give_name_if_anonymous_region_appears_in_arguments(
-                    infcx,
-                    body,
-                    local_names,
-                    *mir_def_id,
-                    fr,
-                    renctx,
-                )
-            })
-            .or_else(|| {
-                self.give_name_if_anonymous_region_appears_in_upvars(infcx.tcx, upvars, fr, renctx)
-            })
-            .or_else(|| {
-                self.give_name_if_anonymous_region_appears_in_output(
-                    infcx,
-                    body,
-                    *mir_def_id,
-                    fr,
-                    renctx,
-                )
-            })
-            .or_else(|| {
-                self.give_name_if_anonymous_region_appears_in_yield_ty(
-                    infcx,
-                    body,
-                    *mir_def_id,
-                    fr,
-                    renctx,
-                )
-            });
+            .give_name_from_error_region(mbcx, fr, renctx)
+            .or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(mbcx, fr, renctx))
+            .or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(mbcx, fr, renctx))
+            .or_else(|| self.give_name_if_anonymous_region_appears_in_output(mbcx, fr, renctx))
+            .or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(mbcx, fr, renctx));
 
         if let Some(ref value) = value {
             renctx.insert(fr, value.clone());
@@ -255,13 +222,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// named variants.
     fn give_name_from_error_region(
         &self,
-        tcx: TyCtxt<'tcx>,
-        mir_def_id: DefId,
+        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         fr: RegionVid,
         renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         let error_region = self.to_error_region(fr)?;
 
+        let tcx = mbcx.infcx.tcx;
+
         debug!("give_region_a_name: error_region = {:?}", error_region);
         match error_region {
             ty::ReEarlyBound(ebr) => {
@@ -308,7 +276,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 }
 
                 ty::BoundRegion::BrEnv => {
-                    let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir");
+                    let mir_hir_id = mbcx
+                        .infcx
+                        .tcx
+                        .hir()
+                        .as_local_hir_id(mbcx.mir_def_id)
+                        .expect("non-local mir");
                     let def_ty = self.universal_regions.defining_ty;
 
                     if let DefiningTy::Closure(def_id, substs) = def_ty {
@@ -373,21 +346,17 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// ```
     fn give_name_if_anonymous_region_appears_in_arguments(
         &self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        body: &Body<'tcx>,
-        local_names: &IndexVec<Local, Option<Symbol>>,
-        mir_def_id: DefId,
+        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         fr: RegionVid,
         renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
-        let argument_index = self.get_argument_index_for_region(infcx.tcx, fr)?;
+        let argument_index = self.get_argument_index_for_region(mbcx.infcx.tcx, fr)?;
 
         let arg_ty =
             self.universal_regions.unnormalized_input_tys[implicit_inputs + argument_index];
         if let Some(region_name) = self.give_name_if_we_can_match_hir_ty_from_argument(
-            infcx,
-            mir_def_id,
+            mbcx,
             fr,
             arg_ty,
             argument_index,
@@ -396,20 +365,19 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             return Some(region_name);
         }
 
-        self.give_name_if_we_cannot_match_hir_ty(infcx, body, local_names, fr, arg_ty, renctx)
+        self.give_name_if_we_cannot_match_hir_ty(mbcx, fr, arg_ty, renctx)
     }
 
     fn give_name_if_we_can_match_hir_ty_from_argument(
         &self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        mir_def_id: DefId,
+        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         needle_fr: RegionVid,
         argument_ty: Ty<'tcx>,
         argument_index: usize,
         renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
-        let mir_hir_id = infcx.tcx.hir().as_local_hir_id(mir_def_id)?;
-        let fn_decl = infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?;
+        let mir_hir_id = mbcx.infcx.tcx.hir().as_local_hir_id(mbcx.mir_def_id)?;
+        let fn_decl = mbcx.infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?;
         let argument_hir_ty: &hir::Ty<'_> = fn_decl.inputs.get(argument_index)?;
         match argument_hir_ty.kind {
             // This indicates a variable with no type annotation, like
@@ -420,7 +388,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             hir::TyKind::Infer => None,
 
             _ => self.give_name_if_we_can_match_hir_ty(
-                infcx.tcx,
+                mbcx.infcx.tcx,
                 needle_fr,
                 argument_ty,
                 argument_hir_ty,
@@ -442,9 +410,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// ```
     fn give_name_if_we_cannot_match_hir_ty(
         &self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        body: &Body<'tcx>,
-        local_names: &IndexVec<Local, Option<Symbol>>,
+        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         needle_fr: RegionVid,
         argument_ty: Ty<'tcx>,
         renctx: &mut RegionErrorNamingCtx,
@@ -452,7 +418,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let counter = renctx.counter;
         let mut highlight = RegionHighlightMode::default();
         highlight.highlighting_region_vid(needle_fr, counter);
-        let type_name = infcx.extract_type_name(&argument_ty, Some(highlight)).0;
+        let type_name = mbcx.infcx.extract_type_name(&argument_ty, Some(highlight)).0;
 
         debug!(
             "give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}",
@@ -460,9 +426,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         );
         let assigned_region_name = if type_name.find(&format!("'{}", counter)).is_some() {
             // Only add a label if we can confirm that a region was labelled.
-            let argument_index = self.get_argument_index_for_region(infcx.tcx, needle_fr)?;
-            let (_, span) =
-                self.get_argument_name_and_span_for_region(body, local_names, argument_index);
+            let argument_index = self.get_argument_index_for_region(mbcx.infcx.tcx, needle_fr)?;
+            let (_, span) = self.get_argument_name_and_span_for_region(
+                &mbcx.body,
+                &mbcx.local_names,
+                argument_index,
+            );
 
             Some(RegionName {
                 // This counter value will already have been used, so this function will increment
@@ -696,14 +665,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// ```
     fn give_name_if_anonymous_region_appears_in_upvars(
         &self,
-        tcx: TyCtxt<'tcx>,
-        upvars: &[Upvar],
+        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         fr: RegionVid,
         renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
-        let upvar_index = self.get_upvar_index_for_region(tcx, fr)?;
+        let upvar_index = self.get_upvar_index_for_region(mbcx.infcx.tcx, fr)?;
         let (upvar_name, upvar_span) =
-            self.get_upvar_name_and_span_for_region(tcx, upvars, upvar_index);
+            self.get_upvar_name_and_span_for_region(mbcx.infcx.tcx, &mbcx.upvars, upvar_index);
         let region_name = renctx.synthesize_region_name();
 
         Some(RegionName {
@@ -718,13 +686,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// or be early bound (named, not in argument).
     fn give_name_if_anonymous_region_appears_in_output(
         &self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        body: &Body<'tcx>,
-        mir_def_id: DefId,
+        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         fr: RegionVid,
         renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
-        let tcx = infcx.tcx;
+        let tcx = mbcx.infcx.tcx;
 
         let return_ty = self.universal_regions.unnormalized_output_ty;
         debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty);
@@ -734,9 +700,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         let mut highlight = RegionHighlightMode::default();
         highlight.highlighting_region_vid(fr, renctx.counter);
-        let type_name = infcx.extract_type_name(&return_ty, Some(highlight)).0;
+        let type_name = mbcx.infcx.extract_type_name(&return_ty, Some(highlight)).0;
 
-        let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir");
+        let mir_hir_id = tcx.hir().as_local_hir_id(mbcx.mir_def_id).expect("non-local mir");
 
         let (return_span, mir_description) = match tcx.hir().get(mir_hir_id) {
             hir::Node::Expr(hir::Expr {
@@ -753,7 +719,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 kind: hir::ImplItemKind::Method(method_sig, _),
                 ..
             }) => (method_sig.decl.output.span(), ""),
-            _ => (body.span, ""),
+            _ => (mbcx.body.span, ""),
         };
 
         Some(RegionName {
@@ -771,9 +737,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
     fn give_name_if_anonymous_region_appears_in_yield_ty(
         &self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        body: &Body<'tcx>,
-        mir_def_id: DefId,
+        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         fr: RegionVid,
         renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
@@ -782,7 +746,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let yield_ty = self.universal_regions.yield_ty?;
         debug!("give_name_if_anonymous_region_appears_in_yield_ty: yield_ty = {:?}", yield_ty,);
 
-        let tcx = infcx.tcx;
+        let tcx = mbcx.infcx.tcx;
 
         if !tcx.any_free_region_meets(&yield_ty, |r| r.to_region_vid() == fr) {
             return None;
@@ -790,15 +754,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         let mut highlight = RegionHighlightMode::default();
         highlight.highlighting_region_vid(fr, renctx.counter);
-        let type_name = infcx.extract_type_name(&yield_ty, Some(highlight)).0;
+        let type_name = mbcx.infcx.extract_type_name(&yield_ty, Some(highlight)).0;
 
-        let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir");
+        let mir_hir_id = tcx.hir().as_local_hir_id(mbcx.mir_def_id).expect("non-local mir");
 
         let yield_span = match tcx.hir().get(mir_hir_id) {
             hir::Node::Expr(hir::Expr {
                 kind: hir::ExprKind::Closure(_, _, _, span, _), ..
             }) => (tcx.sess.source_map().end_point(*span)),
-            _ => body.span,
+            _ => mbcx.body.span,
         };
 
         debug!(
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index a03ac3c33a9..59e6b0bb14e 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -1482,8 +1482,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
         // FIXME(mark-i-m): Would be great to get rid of the naming context.
         let mut region_naming = RegionErrorNamingCtx::new();
-        let mut outlives_suggestion =
-            OutlivesSuggestionBuilder::new(self.mir_def_id, &self.local_names);
+        let mut outlives_suggestion = OutlivesSuggestionBuilder::default();
 
         for nll_error in nll_errors.into_iter() {
             match nll_error {
@@ -1561,11 +1560,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => {
                     if is_reported {
                         let db = self.nonlexical_regioncx.report_error(
-                            &self.body,
-                            &self.local_names,
-                            &self.upvars,
-                            self.infcx,
-                            self.mir_def_id,
+                            self,
                             longer_fr,
                             fr_origin,
                             shorter_fr,
@@ -1591,13 +1586,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         }
 
         // Emit one outlives suggestions for each MIR def we borrowck
-        outlives_suggestion.add_suggestion(
-            &self.body,
-            &self.nonlexical_regioncx,
-            self.infcx,
-            &mut self.errors_buffer,
-            &mut region_naming,
-        );
+        outlives_suggestion.add_suggestion(self, &mut region_naming);
     }
 }