From e0ea756b9f366190dd7a3f00ee8d3fba8237440c Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Fri, 6 Jul 2018 17:25:40 -0300
Subject: [PATCH 01/12] Remove duplicated report word in docs

---
 src/librustc_mir/borrow_check/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index f581b7104a386..46046efa9ba6d 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -366,7 +366,7 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     /// at the time we detect and report a reservation error.
     reservation_error_reported: FxHashSet<Place<'tcx>>,
     /// This field keeps track of errors reported in the checking of moved variables,
-    /// so that we don't report report seemingly duplicate errors.
+    /// so that we don't report seemingly duplicate errors.
     moved_error_reported: FxHashSet<Place<'tcx>>,
     /// This field keeps track of all the local variables that are declared mut and are mutated.
     /// Used for the warning issued by an unused mutable local variable.

From 5dc5c02581ba92716f6d296bc994dcb4e12a5c7b Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Mon, 9 Jul 2018 19:22:09 -0300
Subject: [PATCH 02/12] gcx outlives tcx which outlives a, no need to
 explicitly do gcx: a

---
 src/librustc/ty/context.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index c7bb90bfcb090..41007508c5060 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -849,7 +849,7 @@ impl<'tcx> CommonTypes<'tcx> {
 ///
 /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/ty.html
 #[derive(Copy, Clone)]
-pub struct TyCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+pub struct TyCtxt<'a, 'gcx: 'tcx, 'tcx: 'a> {
     gcx: &'a GlobalCtxt<'gcx>,
     interners: &'a CtxtInterners<'tcx>
 }

From caa11dee50eb6f14dae0d0f06d17b23d92d72ff8 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Tue, 17 Jul 2018 17:59:11 -0300
Subject: [PATCH 03/12] Remove unused lifetime annotation

---
 src/librustc_mir/borrow_check/nll/region_infer/annotation.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs b/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs
index fbff17e589855..7cde06be0c23b 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs
@@ -19,7 +19,7 @@ use borrow_check::nll::region_infer::RegionInferenceContext;
 use borrow_check::nll::universal_regions::DefiningTy;
 use rustc_errors::DiagnosticBuilder;
 
-impl<'gcx, 'tcx> RegionInferenceContext<'tcx> {
+impl<'tcx> RegionInferenceContext<'tcx> {
     /// Write out our state into the `.mir` files.
     pub(crate) fn annotate(&self, err: &mut DiagnosticBuilder<'_>) {
         match self.universal_regions.defining_ty {

From 30313c0ec96ca4a2ab66a08f7affec5a17b281c3 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 18 Jul 2018 16:21:17 -0300
Subject: [PATCH 04/12] Let lifetimes on find be inferred

---
 .../borrow_check/nll/explain_borrow/find_use.rs           | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

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 9fd9d6cd97c59..aa88fa11174b1 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
@@ -19,10 +19,10 @@ use rustc::ty::{RegionVid, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
 use util::liveness::{self, DefUse, LivenessMode};
 
-crate fn find<'cx, 'gcx: 'tcx, 'tcx: 'cx>(
-    mir: &'cx Mir<'tcx>,
-    regioncx: &'cx Rc<RegionInferenceContext<'tcx>>,
-    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+crate fn find<'tcx>(
+    mir: &Mir<'tcx>,
+    regioncx: &Rc<RegionInferenceContext<'tcx>>,
+    tcx: TyCtxt<'_, '_, 'tcx>,
     region_vid: RegionVid,
     start_point: Location,
 ) -> Option<Cause> {

From e4e84fd8ff25c2e033b4efaba3ef55a57713083c Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 18 Jul 2018 16:33:30 -0300
Subject: [PATCH 05/12] Let mir reference lifetime be inferred

---
 src/librustc_mir/dataflow/impls/borrows.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index 5bf54286875a1..995d1340acaf6 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -53,8 +53,8 @@ pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
     _nonlexical_regioncx: Rc<RegionInferenceContext<'tcx>>,
 }
 
-fn precompute_borrows_out_of_scope<'a, 'tcx>(
-    mir: &'a Mir<'tcx>,
+fn precompute_borrows_out_of_scope<'tcx>(
+    mir: &Mir<'tcx>,
     regioncx: &Rc<RegionInferenceContext<'tcx>>,
     borrows_out_of_scope_at_location: &mut FxHashMap<Location, Vec<BorrowIndex>>,
     borrow_index: BorrowIndex,

From bc1eec3fa8bf65736f1e3ea375b22e83bddb38bb Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 18 Jul 2018 16:53:46 -0300
Subject: [PATCH 06/12] Remove unneded lifetimes relations declaration

---
 src/librustc_mir/dataflow/graphviz.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs
index 9096ac1444cfc..f8dc7d2a2a8d1 100644
--- a/src/librustc_mir/dataflow/graphviz.rs
+++ b/src/librustc_mir/dataflow/graphviz.rs
@@ -34,8 +34,8 @@ pub trait MirWithFlowState<'tcx> {
     fn flow_state(&self) -> &DataflowState<Self::BD>;
 }
 
-impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD>
-    where 'tcx: 'a, BD: BitDenotation
+impl<'a, 'tcx, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD>
+    where BD: BitDenotation
 {
     type BD = BD;
     fn node_id(&self) -> NodeId { self.node_id }

From 82e853e2e2e614cd36e4ff996a6ef48eefe1c5b6 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 18 Jul 2018 17:52:49 -0300
Subject: [PATCH 07/12] Remove wrong allow(dead_code) directive

---
 src/librustc_mir/borrow_check/mod.rs | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 46046efa9ba6d..28fd7272b78b0 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -331,7 +331,6 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     result
 }
 
-#[allow(dead_code)]
 pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     tcx: TyCtxt<'cx, 'gcx, 'tcx>,
     mir: &'cx Mir<'tcx>,

From da935e96a11973c4ee3470f1b831eba1ac7a87c3 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Thu, 19 Jul 2018 18:29:26 -0300
Subject: [PATCH 08/12] Remove redundant outlives declarations

---
 src/librustc_mir/borrow_check/nll/type_check/mod.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

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 e23f9b20a10f8..519ddfd1f3026 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -202,7 +202,7 @@ enum FieldAccessError {
 /// The sanitize_XYZ methods here take an MIR object and compute its
 /// type, calling `span_mirbug` and returning an error type if there
 /// is a problem.
-struct TypeVerifier<'a, 'b: 'a, 'gcx: 'b + 'tcx, 'tcx: 'b> {
+struct TypeVerifier<'a, 'b: 'a, 'gcx: 'tcx, 'tcx: 'b> {
     cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>,
     mir: &'a Mir<'tcx>,
     last_span: Span,
@@ -611,7 +611,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
 /// constraints needed for it to be valid and well-typed. Along the
 /// way, it accrues region constraints -- these can later be used by
 /// NLL region checking.
-struct TypeChecker<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
+struct TypeChecker<'a, 'gcx: 'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     param_env: ty::ParamEnv<'gcx>,
     last_span: Span,

From 3d3e0aa57190db4519d4e59ab606f685c21bfc7f Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 18 Jul 2018 18:10:08 -0300
Subject: [PATCH 09/12] Buffer errors in MIR borrow check

(pnkfelix updated to address tidy, and to change the buffer from
`Vec<DiagnosticBuilder<'errs>>` to a `Vec<Diagnostic>` in order to
avoid painful lifetime maintenance.)
---
 src/librustc_errors/diagnostic_builder.rs     | 12 ++++++++
 .../borrow_check/error_reporting.rs           | 29 +++++++++----------
 src/librustc_mir/borrow_check/mod.rs          | 29 ++++++++++++++-----
 src/librustc_mir/borrow_check/move_errors.rs  |  6 ++--
 .../borrow_check/mutability_errors.rs         |  2 +-
 src/librustc_mir/borrow_check/nll/mod.rs      | 12 +++++---
 .../nll/region_infer/error_reporting/mod.rs   | 26 ++++++++++-------
 .../borrow_check/nll/region_infer/mod.rs      | 14 +++++++--
 8 files changed, 87 insertions(+), 43 deletions(-)

diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index 24ece514a47b5..8f99ad87cb8e0 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -88,6 +88,18 @@ impl<'a> DiagnosticBuilder<'a> {
         self.cancel();
     }
 
+    /// Buffers the diagnostic for later emission.
+    pub fn buffer(self, buffered_diagnostics: &mut Vec<Diagnostic>) {
+        // We need to use `ptr::read` because `DiagnosticBuilder`
+        // implements `Drop`.
+        let diagnostic;
+        unsafe {
+            diagnostic = ::std::ptr::read(&self.diagnostic);
+            ::std::mem::forget(self);
+        };
+        buffered_diagnostics.push(diagnostic);
+    }
+
     pub fn is_error(&self) -> bool {
         match self.level {
             Level::Bug |
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 5dca01f8842a0..9e822d28056de 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -58,7 +58,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 Some(name) => format!("`{}`", name),
                 None => "value".to_owned(),
             };
-            self.tcx
+            let mut err = self.tcx
                 .cannot_act_on_uninitialized_variable(
                     span,
                     desired_action.as_noun(),
@@ -66,9 +66,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         .describe_place_with_options(place, IncludingDowncast(true))
                         .unwrap_or("_".to_owned()),
                     Origin::Mir,
-                )
-                .span_label(span, format!("use of possibly uninitialized {}", item_msg))
-                .emit();
+                );
+            err.span_label(span, format!("use of possibly uninitialized {}", item_msg));
+            err.buffer(&mut self.errors_buffer);
         } else {
             let msg = ""; //FIXME: add "partially " or "collaterally "
 
@@ -143,7 +143,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 }
             }
 
-            err.emit();
+            err.buffer(&mut self.errors_buffer);
         }
     }
 
@@ -173,7 +173,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         );
         err.span_label(span, format!("move out of {} occurs here", value_msg));
         self.explain_why_borrow_contains_point(context, borrow, None, &mut err);
-        err.emit();
+        err.buffer(&mut self.errors_buffer);
     }
 
     pub(super) fn report_use_while_mutably_borrowed(
@@ -194,8 +194,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         );
 
         self.explain_why_borrow_contains_point(context, borrow, None, &mut err);
-
-        err.emit();
+        err.buffer(&mut self.errors_buffer);
     }
 
     /// Finds the span of arguments of a closure (within `maybe_closure_span`) and its usage of
@@ -391,7 +390,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
         self.explain_why_borrow_contains_point(context, issued_borrow, None, &mut err);
 
-        err.emit();
+        err.buffer(&mut self.errors_buffer);
     }
 
     pub(super) fn report_borrowed_value_does_not_live_long_enough(
@@ -513,7 +512,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             format!("`{}` dropped here while still borrowed", name),
         );
         self.explain_why_borrow_contains_point(context, borrow, None, &mut err);
-        err.emit();
+        err.buffer(&mut self.errors_buffer);
     }
 
     fn report_scoped_temporary_value_does_not_live_long_enough(
@@ -535,7 +534,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         );
         err.note("consider using a `let` binding to increase its lifetime");
         self.explain_why_borrow_contains_point(context, borrow, None, &mut err);
-        err.emit();
+        err.buffer(&mut self.errors_buffer);
     }
 
     fn report_unscoped_local_value_does_not_live_long_enough(
@@ -563,7 +562,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         err.span_label(drop_span, "borrowed value only lives until here");
 
         self.explain_why_borrow_contains_point(context, borrow, kind_place, &mut err);
-        err.emit();
+        err.buffer(&mut self.errors_buffer);
     }
 
     fn report_unscoped_temporary_value_does_not_live_long_enough(
@@ -589,7 +588,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         err.span_label(drop_span, "temporary value only lives until here");
 
         self.explain_why_borrow_contains_point(context, borrow, None, &mut err);
-        err.emit();
+        err.buffer(&mut self.errors_buffer);
     }
 
     pub(super) fn report_illegal_mutation_of_borrowed(
@@ -608,7 +607,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
         self.explain_why_borrow_contains_point(context, loan, None, &mut err);
 
-        err.emit();
+        err.buffer(&mut self.errors_buffer);
     }
 
     /// Reports an illegal reassignment; for example, an assignment to
@@ -679,7 +678,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             }
         }
         err.span_label(span, msg);
-        err.emit();
+        err.buffer(&mut self.errors_buffer);
     }
 }
 
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 28fd7272b78b0..08500efe8efed 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -23,6 +23,7 @@ use rustc::mir::{Terminator, TerminatorKind};
 use rustc::ty::query::Providers;
 use rustc::ty::{self, ParamEnv, TyCtxt};
 
+use rustc_errors::{Diagnostic, DiagnosticBuilder};
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_set::IdxSetBuf;
@@ -148,6 +149,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     let mir = &mir; // no further changes
     let location_table = &LocationTable::new(mir);
 
+    let mut errors_buffer = Vec::new();
     let (move_data, move_errors): (MoveData<'tcx>, Option<Vec<MoveError<'tcx>>>) =
         match MoveData::gather_moves(mir, tcx) {
             Ok(move_data) => (move_data, None),
@@ -214,6 +216,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         &mut flow_inits,
         &mdpe.move_data,
         &borrow_set,
+        &mut errors_buffer,
     );
     let regioncx = Rc::new(regioncx);
 
@@ -252,6 +255,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         access_place_error_reported: FxHashSet(),
         reservation_error_reported: FxHashSet(),
         moved_error_reported: FxHashSet(),
+        errors_buffer,
         nonlexical_regioncx: regioncx,
         used_mut: FxHashSet(),
         used_mut_upvars: SmallVec::new(),
@@ -287,10 +291,12 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
 
     debug!("mbcx.used_mut: {:?}", mbcx.used_mut);
 
+    let used_mut = mbcx.used_mut;
+
     for local in mbcx
         .mir
         .mut_vars_and_args_iter()
-        .filter(|local| !mbcx.used_mut.contains(local))
+        .filter(|local| !used_mut.contains(local))
     {
         if let ClearCrossCrate::Set(ref vsi) = mbcx.mir.source_scope_local_data {
             let local_decl = &mbcx.mir.local_decls[local];
@@ -311,16 +317,22 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
             let span = local_decl.source_info.span;
             let mut_span = tcx.sess.codemap().span_until_non_whitespace(span);
 
-            tcx.struct_span_lint_node(
+            let mut err = tcx.struct_span_lint_node(
                 UNUSED_MUT,
                 vsi[local_decl.source_info.scope].lint_root,
                 span,
                 "variable does not need to be mutable",
-            ).span_suggestion_short(mut_span, "remove this `mut`", "".to_owned())
-                .emit();
+            );
+            err.span_suggestion_short(mut_span, "remove this `mut`", "".to_owned());
+
+            err.buffer(&mut mbcx.errors_buffer);
         }
     }
 
+    for diag in mbcx.errors_buffer.drain(..) {
+        DiagnosticBuilder::new_diagnostic(mbcx.tcx.sess.diagnostic(), diag).emit();
+    }
+
     let result = BorrowCheckResult {
         closure_requirements: opt_closure_req,
         used_mut_upvars: mbcx.used_mut_upvars,
@@ -367,6 +379,8 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     /// This field keeps track of errors reported in the checking of moved variables,
     /// so that we don't report seemingly duplicate errors.
     moved_error_reported: FxHashSet<Place<'tcx>>,
+    /// Errors to be reported buffer
+    errors_buffer: Vec<Diagnostic>,
     /// This field keeps track of all the local variables that are declared mut and are mutated.
     /// Used for the warning issued by an unused mutable local variable.
     used_mut: FxHashSet<Local>,
@@ -1353,13 +1367,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         debug!("check_for_local_borrow({:?})", borrow);
 
         if borrow_of_local_data(&borrow.borrowed_place) {
-            self.tcx
+            let err = self.tcx
                 .cannot_borrow_across_generator_yield(
                     self.retrieve_borrow_span(borrow),
                     yield_span,
                     Origin::Mir,
-                )
-                .emit();
+                );
+
+            err.buffer(&mut self.errors_buffer);
         }
     }
 
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs
index b7ba5c855b996..eacdbe8e9455e 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/move_errors.rs
@@ -59,7 +59,7 @@ enum GroupedMoveError<'tcx> {
 }
 
 impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
-    pub(crate) fn report_move_errors(&self, move_errors: Vec<MoveError<'tcx>>) {
+    pub(crate) fn report_move_errors(&mut self, move_errors: Vec<MoveError<'tcx>>) {
         let grouped_errors = self.group_move_errors(move_errors);
         for error in grouped_errors {
             self.report(error);
@@ -218,7 +218,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
         };
     }
 
-    fn report(&self, error: GroupedMoveError<'tcx>) {
+    fn report(&mut self, error: GroupedMoveError<'tcx>) {
         let (mut err, err_span) = {
             let (span, kind): (Span, &IllegalMoveOriginKind) = match error {
                 GroupedMoveError::MovesFromMatchPlace { span, ref kind, .. }
@@ -286,7 +286,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
         };
 
         self.add_move_hints(error, &mut err, err_span);
-        err.emit();
+        err.buffer(&mut self.errors_buffer);
     }
 
     fn add_move_hints(
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index 2a074a84e63e5..760d0a91b795c 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -378,7 +378,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             }
         }
 
-        err.emit();
+        err.buffer(&mut self.errors_buffer);
     }
 
     // Does this place refer to what the user sees as an upvar
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index 76f8fa206be5d..b8b38b583195e 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -23,6 +23,7 @@ use rustc::infer::InferCtxt;
 use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir};
 use rustc::ty::{self, RegionKind, RegionVid};
 use rustc::util::nodemap::FxHashMap;
+use rustc_errors::Diagnostic;
 use std::collections::BTreeSet;
 use std::fmt::Debug;
 use std::env;
@@ -91,6 +92,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'cx, 'gcx, 'tcx>>,
     move_data: &MoveData<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
+    errors_buffer: &mut Vec<Diagnostic>,
 ) -> (
     RegionInferenceContext<'tcx>,
     Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
@@ -190,7 +192,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     });
 
     // Solve the region constraints.
-    let closure_region_requirements = regioncx.solve(infcx, &mir, def_id);
+    let closure_region_requirements = regioncx.solve(infcx, &mir, def_id, errors_buffer);
 
     // Dump MIR results into a file, if that is enabled. This let us
     // write unit-tests, as well as helping with debugging.
@@ -205,7 +207,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
 
     // We also have a `#[rustc_nll]` annotation that causes us to dump
     // information
-    dump_annotation(infcx, &mir, def_id, &regioncx, &closure_region_requirements);
+    dump_annotation(infcx, &mir, def_id, &regioncx, &closure_region_requirements, errors_buffer);
 
     (regioncx, polonius_output, closure_region_requirements)
 }
@@ -323,6 +325,7 @@ fn dump_annotation<'a, 'gcx, 'tcx>(
     mir_def_id: DefId,
     regioncx: &RegionInferenceContext,
     closure_region_requirements: &Option<ClosureRegionRequirements>,
+    errors_buffer: &mut Vec<Diagnostic>,
 ) {
     let tcx = infcx.tcx;
     let base_def_id = tcx.closure_base_def_id(mir_def_id);
@@ -357,14 +360,15 @@ fn dump_annotation<'a, 'gcx, 'tcx>(
             Ok(())
         }).unwrap();
 
-        err.emit();
+        err.buffer(errors_buffer);
     } else {
         let mut err = tcx
             .sess
             .diagnostic()
             .span_note_diag(mir.span, "No external requirements");
         regioncx.annotate(&mut err);
-        err.emit();
+
+        err.buffer(errors_buffer);
     }
 }
 
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
index c89dc889b5e39..131e1defc1f9e 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
@@ -18,6 +18,7 @@ use rustc::mir::{self, Location, Mir, Place, Rvalue, StatementKind, TerminatorKi
 use rustc::ty::RegionVid;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_errors::Diagnostic;
 use std::fmt;
 use syntax_pos::Span;
 
@@ -199,6 +200,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         fr: RegionVid,
         outlived_fr: RegionVid,
         blame_span: Span,
+        errors_buffer: &mut Vec<Diagnostic>,
     ) {
         debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
 
@@ -247,9 +249,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         match category {
             ConstraintCategory::AssignmentToUpvar |
             ConstraintCategory::CallArgumentToUpvar =>
-                self.report_closure_error(mir, infcx, mir_def_id, fr, outlived_fr, category, span),
+                self.report_closure_error(
+                    mir, infcx, mir_def_id, fr, outlived_fr, category, span, errors_buffer),
             _ =>
-                self.report_general_error(mir, infcx, mir_def_id, fr, outlived_fr, category, span),
+                self.report_general_error(
+                    mir, infcx, mir_def_id, fr, outlived_fr, category, span, errors_buffer),
         }
     }
 
@@ -262,6 +266,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         outlived_fr: RegionVid,
         category: &ConstraintCategory,
         span: &Span,
+        errors_buffer: &mut Vec<Diagnostic>,
     ) {
         let fr_name_and_span  = self.get_var_name_and_span_for_region(
             infcx.tcx, mir, fr);
@@ -269,11 +274,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             infcx.tcx, mir,outlived_fr);
 
         if fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none() {
-            return self.report_general_error(mir, infcx, mir_def_id, fr, outlived_fr, category,
-                                             span);
+            return self.report_general_error(
+                mir, infcx, mir_def_id, fr, outlived_fr, category, span, errors_buffer);
         }
 
-        let diag = &mut infcx.tcx.sess.struct_span_err(
+        let mut diag = infcx.tcx.sess.struct_span_err(
             *span, &format!("borrowed data escapes outside of closure"),
         );
 
@@ -297,7 +302,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             }
         }
 
-        diag.emit();
+        diag.buffer(errors_buffer);
     }
 
     fn report_general_error(
@@ -309,23 +314,24 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         outlived_fr: RegionVid,
         category: &ConstraintCategory,
         span: &Span,
+        errors_buffer: &mut Vec<Diagnostic>,
     ) {
-        let diag = &mut infcx.tcx.sess.struct_span_err(
+        let mut diag = infcx.tcx.sess.struct_span_err(
             *span, &format!("unsatisfied lifetime constraints"), // FIXME
         );
 
         let counter = &mut 1;
         let fr_name = self.give_region_a_name(
-            infcx.tcx, mir, mir_def_id, fr, counter, diag);
+            infcx.tcx, mir, mir_def_id, fr, counter, &mut diag);
         let outlived_fr_name = self.give_region_a_name(
-            infcx.tcx, mir, mir_def_id, outlived_fr, counter, diag);
+            infcx.tcx, mir, mir_def_id, outlived_fr, counter, &mut diag);
 
         diag.span_label(*span, format!(
             "{} requires that `{}` must outlive `{}`",
             category, fr_name, outlived_fr_name,
         ));
 
-        diag.emit();
+        diag.buffer(errors_buffer);
     }
 
     // Find some constraint `X: Y` where:
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 5159fdc9fbabf..37df311805edc 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -30,6 +30,7 @@ use rustc::util::common;
 use rustc_data_structures::graph::scc::Sccs;
 use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf};
 use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_errors::Diagnostic;
 
 use std::rc::Rc;
 
@@ -360,11 +361,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
         mir: &Mir<'tcx>,
         mir_def_id: DefId,
+        errors_buffer: &mut Vec<Diagnostic>,
     ) -> Option<ClosureRegionRequirements<'gcx>> {
         common::time(
             infcx.tcx.sess,
             &format!("solve_nll_region_constraints({:?})", mir_def_id),
-            || self.solve_inner(infcx, mir, mir_def_id),
+            || self.solve_inner(infcx, mir, mir_def_id, errors_buffer),
         )
     }
 
@@ -373,6 +375,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
         mir: &Mir<'tcx>,
         mir_def_id: DefId,
+        errors_buffer: &mut Vec<Diagnostic>,
     ) -> Option<ClosureRegionRequirements<'gcx>> {
         self.propagate_constraints(mir);
 
@@ -389,7 +392,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         self.check_type_tests(infcx, mir, mir_def_id, outlives_requirements.as_mut());
 
-        self.check_universal_regions(infcx, mir, mir_def_id, outlives_requirements.as_mut());
+        self.check_universal_regions(
+            infcx, mir, mir_def_id, outlives_requirements.as_mut(), errors_buffer);
 
         let outlives_requirements = outlives_requirements.unwrap_or(vec![]);
 
@@ -834,6 +838,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         mir: &Mir<'tcx>,
         mir_def_id: DefId,
         mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
+        errors_buffer: &mut Vec<Diagnostic>,
     ) {
         // The universal regions are always found in a prefix of the
         // full list.
@@ -851,6 +856,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 mir_def_id,
                 fr,
                 &mut propagated_outlives_requirements,
+                errors_buffer,
             );
         }
     }
@@ -870,6 +876,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         mir_def_id: DefId,
         longer_fr: RegionVid,
         propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
+        errors_buffer: &mut Vec<Diagnostic>,
     ) {
         debug!("check_universal_region(fr={:?})", longer_fr);
 
@@ -924,7 +931,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             // Note: in this case, we use the unapproximated regions
             // to report the error. This gives better error messages
             // in some cases.
-            self.report_error(mir, infcx, mir_def_id, longer_fr, shorter_fr, blame_span);
+            self.report_error(
+                mir, infcx, mir_def_id, longer_fr, shorter_fr, blame_span, errors_buffer);
         }
     }
 }

From 87e729f58a440c2b384f4871fb68f07afdbd3ba6 Mon Sep 17 00:00:00 2001
From: "Felix S. Klock II" <pnkfelix@pnkfx.org>
Date: Wed, 18 Jul 2018 22:34:01 +0200
Subject: [PATCH 10/12] thread the `errors_buffer` down into `nll::type_check`.

Right now its solely used for `check_local`, which ... I guess is not surprising?
---
 src/librustc_mir/borrow_check/nll/mod.rs      |  1 +
 .../borrow_check/nll/type_check/mod.rs        | 48 +++++++++++++------
 2 files changed, 34 insertions(+), 15 deletions(-)

diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index b8b38b583195e..edc701bad1eb3 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -122,6 +122,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
         flow_inits,
         move_data,
         elements,
+        errors_buffer,
     );
 
     if let Some(all_facts) = &mut all_facts {
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 519ddfd1f3026..a80cd9ff1a4be 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -41,6 +41,7 @@ use std::rc::Rc;
 use syntax_pos::{Span, DUMMY_SP};
 use transform::{MirPass, MirSource};
 use util::liveness::LivenessResults;
+use rustc_errors::Diagnostic;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::Idx;
@@ -102,6 +103,7 @@ mod liveness;
 ///   constraints for the regions in the types of variables
 /// - `flow_inits` -- results of a maybe-init dataflow analysis
 /// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
+/// - `errors_buffer` -- errors are sent here for future reporting
 pub(crate) fn type_check<'gcx, 'tcx>(
     infcx: &InferCtxt<'_, 'gcx, 'tcx>,
     param_env: ty::ParamEnv<'gcx>,
@@ -115,6 +117,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
     flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
     move_data: &MoveData<'tcx>,
     elements: &Rc<RegionValueElements>,
+    errors_buffer: &mut Vec<Diagnostic>,
 ) -> MirTypeckRegionConstraints<'tcx> {
     let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
     let mut constraints = MirTypeckRegionConstraints {
@@ -140,14 +143,13 @@ pub(crate) fn type_check<'gcx, 'tcx>(
             &universal_regions.region_bound_pairs,
             Some(implicit_region_bound),
             Some(&mut borrowck_context),
+            Some(errors_buffer),
             |cx| {
                 liveness::generate(cx, mir, liveness, flow_inits, move_data);
-
                 cx.equate_inputs_and_outputs(mir, mir_def_id, universal_regions);
             },
         );
     }
-
     constraints
 }
 
@@ -159,6 +161,7 @@ fn type_check_internal<'a, 'gcx, 'tcx, F>(
     region_bound_pairs: &'a [(ty::Region<'tcx>, GenericKind<'tcx>)],
     implicit_region_bound: Option<ty::Region<'tcx>>,
     borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>,
+    errors_buffer: Option<&mut Vec<Diagnostic>>,
     mut extra: F,
 )
     where F: FnMut(&mut TypeChecker<'a, 'gcx, 'tcx>)
@@ -180,7 +183,7 @@ fn type_check_internal<'a, 'gcx, 'tcx, F>(
 
     if !errors_reported {
         // if verifier failed, don't do further checks to avoid ICEs
-        checker.typeck_mir(mir);
+        checker.typeck_mir(mir, errors_buffer);
     }
 
     extra(&mut checker);
@@ -1227,7 +1230,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         }
     }
 
-    fn check_local(&mut self, mir: &Mir<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>) {
+    fn check_local(&mut self,
+                   mir: &Mir<'tcx>,
+                   local: Local,
+                   local_decl: &LocalDecl<'tcx>,
+                   errors_buffer: &mut Option<&mut Vec<Diagnostic>>)
+    {
         match mir.local_kind(local) {
             LocalKind::ReturnPointer | LocalKind::Arg => {
                 // return values of normal functions are required to be
@@ -1255,14 +1263,21 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             // slot or local, so to find all unsized rvalues it is enough
             // to check all temps, return slots and locals.
             if let None = self.reported_errors.replace((ty, span)) {
-                span_err!(
-                    self.tcx().sess,
-                    span,
-                    E0161,
-                    "cannot move a value of type {0}: the size of {0} \
-                     cannot be statically determined",
-                    ty
-                );
+                let mut diag = struct_span_err!(self.tcx().sess,
+                                                span,
+                                                E0161,
+                                                "cannot move a value of type {0}: the size of {0} \
+                                                 cannot be statically determined",
+                                                ty);
+                if let Some(ref mut errors_buffer) = *errors_buffer {
+                    diag.buffer(errors_buffer);
+                } else {
+                    // we're allowed to use emit() here because the
+                    // NLL migration will be turned on (and thus
+                    // errors will need to be buffered) *only if*
+                    // errors_buffer is Some.
+                    diag.emit();
+                }
             }
         }
     }
@@ -1742,12 +1757,15 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         })
     }
 
-    fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
+    fn typeck_mir(&mut self,
+                  mir: &Mir<'tcx>,
+                  mut errors_buffer: Option<&mut Vec<Diagnostic>>)
+    {
         self.last_span = mir.span;
         debug!("run_on_mir: {:?}", mir.span);
 
         for (local, local_decl) in mir.local_decls.iter_enumerated() {
-            self.check_local(mir, local, local_decl);
+            self.check_local(mir, local, local_decl, &mut errors_buffer);
         }
 
         for (block, block_data) in mir.basic_blocks().iter_enumerated() {
@@ -1812,7 +1830,7 @@ impl MirPass for TypeckMir {
 
         let param_env = tcx.param_env(def_id);
         tcx.infer_ctxt().enter(|infcx| {
-            type_check_internal(&infcx, def_id, param_env, mir, &[], None, None, |_| ());
+            type_check_internal(&infcx, def_id, param_env, mir, &[], None, None, None, |_| ());
 
             // For verification purposes, we just ignore the resulting
             // region constraint sets. Not our problem. =)

From ec005ccf84e470a70f8bb8b5347ab8e793fb30a3 Mon Sep 17 00:00:00 2001
From: "Felix S. Klock II" <pnkfelix@pnkfx.org>
Date: Wed, 18 Jul 2018 23:17:22 +0200
Subject: [PATCH 11/12] Separate the construction of a generic bound failure
 from its emission.

---
 src/librustc/infer/error_reporting/mod.rs | 24 +++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 1ec9c9489e9b7..4ad60f2f85e2c 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -1086,6 +1086,23 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         bound_kind: GenericKind<'tcx>,
         sub: Region<'tcx>,
     ) {
+        self.construct_generic_bound_failure(region_scope_tree,
+                                             span,
+                                             origin,
+                                             bound_kind,
+                                             sub)
+            .emit()
+    }
+
+    pub fn construct_generic_bound_failure(
+        &self,
+        region_scope_tree: &region::ScopeTree,
+        span: Span,
+        origin: Option<SubregionOrigin<'tcx>>,
+        bound_kind: GenericKind<'tcx>,
+        sub: Region<'tcx>,
+    ) -> DiagnosticBuilder<'a>
+    {
         // Attempt to obtain the span of the parameter so we can
         // suggest adding an explicit lifetime bound to it.
         let type_param_span = match (self.in_progress_tables, bound_kind) {
@@ -1139,14 +1156,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             trait_item_def_id,
         }) = origin
         {
-            self.report_extra_impl_obligation(
+            return self.report_extra_impl_obligation(
                 span,
                 item_name,
                 impl_item_def_id,
                 trait_item_def_id,
                 &format!("`{}: {}`", bound_kind, sub),
-            ).emit();
-            return;
+            );
         }
 
         fn binding_suggestion<'tcx, S: fmt::Display>(
@@ -1229,7 +1245,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         if let Some(origin) = origin {
             self.note_region_origin(&mut err, &origin);
         }
-        err.emit();
+        err
     }
 
     fn report_sub_sup_conflict(

From 1a0294bb84d2b4aaf66634f61279bca5e132d1dc Mon Sep 17 00:00:00 2001
From: "Felix S. Klock II" <pnkfelix@pnkfx.org>
Date: Wed, 18 Jul 2018 23:23:21 +0200
Subject: [PATCH 12/12] Thread the `errors_buffer` down through the NLL
 region_infer code.

---
 .../borrow_check/nll/region_infer/mod.rs             | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

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 37df311805edc..52f596f61c2e8 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -390,7 +390,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             None
         };
 
-        self.check_type_tests(infcx, mir, mir_def_id, outlives_requirements.as_mut());
+        self.check_type_tests(
+            infcx, mir, mir_def_id, outlives_requirements.as_mut(), errors_buffer);
 
         self.check_universal_regions(
             infcx, mir, mir_def_id, outlives_requirements.as_mut(), errors_buffer);
@@ -480,6 +481,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         mir: &Mir<'tcx>,
         mir_def_id: DefId,
         mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
+        errors_buffer: &mut Vec<Diagnostic>,
     ) {
         let tcx = infcx.tcx;
 
@@ -506,13 +508,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             if let Some(lower_bound_region) = lower_bound_region {
                 let region_scope_tree = &tcx.region_scope_tree(mir_def_id);
                 let type_test_span = type_test.locations.span(mir);
-                infcx.report_generic_bound_failure(
+                infcx.construct_generic_bound_failure(
                     region_scope_tree,
                     type_test_span,
                     None,
                     type_test.generic_kind,
                     lower_bound_region,
-                );
+                ).buffer(errors_buffer);
             } else {
                 // FIXME. We should handle this case better. It
                 // indicates that we have e.g. some region variable
@@ -524,10 +526,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 // iterating over the universal regions and reporting
                 // an error that multiple bounds are required.
                 let type_test_span = type_test.locations.span(mir);
-                tcx.sess.span_err(
+                tcx.sess.struct_span_err(
                     type_test_span,
                     &format!("`{}` does not live long enough", type_test.generic_kind,),
-                );
+                ).buffer(errors_buffer);
             }
         }
     }