Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 8dbbd81

Browse files
committedJul 23, 2018
Auto merge of #52566 - pnkfelix:buffer-nll-errors-for-z-borrowck-migrate, r=nikomatsakis
Buffer NLL errors Buffer the errors generated during MIR-borrowck (aka NLL). This is the first big step towards resolving issue #46908.
2 parents 6bb50f5 + 1a0294b commit 8dbbd81

File tree

15 files changed

+161
-81
lines changed

15 files changed

+161
-81
lines changed
 

‎src/librustc/infer/error_reporting/mod.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,6 +1086,23 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
10861086
bound_kind: GenericKind<'tcx>,
10871087
sub: Region<'tcx>,
10881088
) {
1089+
self.construct_generic_bound_failure(region_scope_tree,
1090+
span,
1091+
origin,
1092+
bound_kind,
1093+
sub)
1094+
.emit()
1095+
}
1096+
1097+
pub fn construct_generic_bound_failure(
1098+
&self,
1099+
region_scope_tree: &region::ScopeTree,
1100+
span: Span,
1101+
origin: Option<SubregionOrigin<'tcx>>,
1102+
bound_kind: GenericKind<'tcx>,
1103+
sub: Region<'tcx>,
1104+
) -> DiagnosticBuilder<'a>
1105+
{
10891106
// Attempt to obtain the span of the parameter so we can
10901107
// suggest adding an explicit lifetime bound to it.
10911108
let type_param_span = match (self.in_progress_tables, bound_kind) {
@@ -1139,14 +1156,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
11391156
trait_item_def_id,
11401157
}) = origin
11411158
{
1142-
self.report_extra_impl_obligation(
1159+
return self.report_extra_impl_obligation(
11431160
span,
11441161
item_name,
11451162
impl_item_def_id,
11461163
trait_item_def_id,
11471164
&format!("`{}: {}`", bound_kind, sub),
1148-
).emit();
1149-
return;
1165+
);
11501166
}
11511167

11521168
fn binding_suggestion<'tcx, S: fmt::Display>(
@@ -1229,7 +1245,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
12291245
if let Some(origin) = origin {
12301246
self.note_region_origin(&mut err, &origin);
12311247
}
1232-
err.emit();
1248+
err
12331249
}
12341250

12351251
fn report_sub_sup_conflict(

‎src/librustc/ty/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,7 @@ impl<'tcx> CommonTypes<'tcx> {
849849
///
850850
/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/ty.html
851851
#[derive(Copy, Clone)]
852-
pub struct TyCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
852+
pub struct TyCtxt<'a, 'gcx: 'tcx, 'tcx: 'a> {
853853
gcx: &'a GlobalCtxt<'gcx>,
854854
interners: &'a CtxtInterners<'tcx>
855855
}

‎src/librustc_errors/diagnostic_builder.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,18 @@ impl<'a> DiagnosticBuilder<'a> {
8888
self.cancel();
8989
}
9090

91+
/// Buffers the diagnostic for later emission.
92+
pub fn buffer(self, buffered_diagnostics: &mut Vec<Diagnostic>) {
93+
// We need to use `ptr::read` because `DiagnosticBuilder`
94+
// implements `Drop`.
95+
let diagnostic;
96+
unsafe {
97+
diagnostic = ::std::ptr::read(&self.diagnostic);
98+
::std::mem::forget(self);
99+
};
100+
buffered_diagnostics.push(diagnostic);
101+
}
102+
91103
pub fn is_error(&self) -> bool {
92104
match self.level {
93105
Level::Bug |

‎src/librustc_mir/borrow_check/error_reporting.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
5858
Some(name) => format!("`{}`", name),
5959
None => "value".to_owned(),
6060
};
61-
self.tcx
61+
let mut err = self.tcx
6262
.cannot_act_on_uninitialized_variable(
6363
span,
6464
desired_action.as_noun(),
6565
&self
6666
.describe_place_with_options(place, IncludingDowncast(true))
6767
.unwrap_or("_".to_owned()),
6868
Origin::Mir,
69-
)
70-
.span_label(span, format!("use of possibly uninitialized {}", item_msg))
71-
.emit();
69+
);
70+
err.span_label(span, format!("use of possibly uninitialized {}", item_msg));
71+
err.buffer(&mut self.errors_buffer);
7272
} else {
7373
let msg = ""; //FIXME: add "partially " or "collaterally "
7474

@@ -143,7 +143,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
143143
}
144144
}
145145

146-
err.emit();
146+
err.buffer(&mut self.errors_buffer);
147147
}
148148
}
149149

@@ -173,7 +173,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
173173
);
174174
err.span_label(span, format!("move out of {} occurs here", value_msg));
175175
self.explain_why_borrow_contains_point(context, borrow, None, &mut err);
176-
err.emit();
176+
err.buffer(&mut self.errors_buffer);
177177
}
178178

179179
pub(super) fn report_use_while_mutably_borrowed(
@@ -194,8 +194,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
194194
);
195195

196196
self.explain_why_borrow_contains_point(context, borrow, None, &mut err);
197-
198-
err.emit();
197+
err.buffer(&mut self.errors_buffer);
199198
}
200199

201200
/// 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> {
391390

392391
self.explain_why_borrow_contains_point(context, issued_borrow, None, &mut err);
393392

394-
err.emit();
393+
err.buffer(&mut self.errors_buffer);
395394
}
396395

397396
pub(super) fn report_borrowed_value_does_not_live_long_enough(
@@ -513,7 +512,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
513512
format!("`{}` dropped here while still borrowed", name),
514513
);
515514
self.explain_why_borrow_contains_point(context, borrow, None, &mut err);
516-
err.emit();
515+
err.buffer(&mut self.errors_buffer);
517516
}
518517

519518
fn report_scoped_temporary_value_does_not_live_long_enough(
@@ -535,7 +534,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
535534
);
536535
err.note("consider using a `let` binding to increase its lifetime");
537536
self.explain_why_borrow_contains_point(context, borrow, None, &mut err);
538-
err.emit();
537+
err.buffer(&mut self.errors_buffer);
539538
}
540539

541540
fn report_unscoped_local_value_does_not_live_long_enough(
@@ -563,7 +562,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
563562
err.span_label(drop_span, "borrowed value only lives until here");
564563

565564
self.explain_why_borrow_contains_point(context, borrow, kind_place, &mut err);
566-
err.emit();
565+
err.buffer(&mut self.errors_buffer);
567566
}
568567

569568
fn report_unscoped_temporary_value_does_not_live_long_enough(
@@ -589,7 +588,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
589588
err.span_label(drop_span, "temporary value only lives until here");
590589

591590
self.explain_why_borrow_contains_point(context, borrow, None, &mut err);
592-
err.emit();
591+
err.buffer(&mut self.errors_buffer);
593592
}
594593

595594
pub(super) fn report_illegal_mutation_of_borrowed(
@@ -608,7 +607,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
608607

609608
self.explain_why_borrow_contains_point(context, loan, None, &mut err);
610609

611-
err.emit();
610+
err.buffer(&mut self.errors_buffer);
612611
}
613612

614613
/// Reports an illegal reassignment; for example, an assignment to
@@ -679,7 +678,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
679678
}
680679
}
681680
err.span_label(span, msg);
682-
err.emit();
681+
err.buffer(&mut self.errors_buffer);
683682
}
684683
}
685684

‎src/librustc_mir/borrow_check/mod.rs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use rustc::mir::{Terminator, TerminatorKind};
2323
use rustc::ty::query::Providers;
2424
use rustc::ty::{self, ParamEnv, TyCtxt};
2525

26+
use rustc_errors::{Diagnostic, DiagnosticBuilder};
2627
use rustc_data_structures::graph::dominators::Dominators;
2728
use rustc_data_structures::fx::FxHashSet;
2829
use rustc_data_structures::indexed_set::IdxSetBuf;
@@ -148,6 +149,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
148149
let mir = &mir; // no further changes
149150
let location_table = &LocationTable::new(mir);
150151

152+
let mut errors_buffer = Vec::new();
151153
let (move_data, move_errors): (MoveData<'tcx>, Option<Vec<MoveError<'tcx>>>) =
152154
match MoveData::gather_moves(mir, tcx) {
153155
Ok(move_data) => (move_data, None),
@@ -214,6 +216,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
214216
&mut flow_inits,
215217
&mdpe.move_data,
216218
&borrow_set,
219+
&mut errors_buffer,
217220
);
218221
let regioncx = Rc::new(regioncx);
219222

@@ -252,6 +255,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
252255
access_place_error_reported: FxHashSet(),
253256
reservation_error_reported: FxHashSet(),
254257
moved_error_reported: FxHashSet(),
258+
errors_buffer,
255259
nonlexical_regioncx: regioncx,
256260
used_mut: FxHashSet(),
257261
used_mut_upvars: SmallVec::new(),
@@ -287,10 +291,12 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
287291

288292
debug!("mbcx.used_mut: {:?}", mbcx.used_mut);
289293

294+
let used_mut = mbcx.used_mut;
295+
290296
for local in mbcx
291297
.mir
292298
.mut_vars_and_args_iter()
293-
.filter(|local| !mbcx.used_mut.contains(local))
299+
.filter(|local| !used_mut.contains(local))
294300
{
295301
if let ClearCrossCrate::Set(ref vsi) = mbcx.mir.source_scope_local_data {
296302
let local_decl = &mbcx.mir.local_decls[local];
@@ -311,16 +317,22 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
311317
let span = local_decl.source_info.span;
312318
let mut_span = tcx.sess.codemap().span_until_non_whitespace(span);
313319

314-
tcx.struct_span_lint_node(
320+
let mut err = tcx.struct_span_lint_node(
315321
UNUSED_MUT,
316322
vsi[local_decl.source_info.scope].lint_root,
317323
span,
318324
"variable does not need to be mutable",
319-
).span_suggestion_short(mut_span, "remove this `mut`", "".to_owned())
320-
.emit();
325+
);
326+
err.span_suggestion_short(mut_span, "remove this `mut`", "".to_owned());
327+
328+
err.buffer(&mut mbcx.errors_buffer);
321329
}
322330
}
323331

332+
for diag in mbcx.errors_buffer.drain(..) {
333+
DiagnosticBuilder::new_diagnostic(mbcx.tcx.sess.diagnostic(), diag).emit();
334+
}
335+
324336
let result = BorrowCheckResult {
325337
closure_requirements: opt_closure_req,
326338
used_mut_upvars: mbcx.used_mut_upvars,
@@ -331,7 +343,6 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
331343
result
332344
}
333345

334-
#[allow(dead_code)]
335346
pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
336347
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
337348
mir: &'cx Mir<'tcx>,
@@ -366,8 +377,10 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
366377
/// at the time we detect and report a reservation error.
367378
reservation_error_reported: FxHashSet<Place<'tcx>>,
368379
/// This field keeps track of errors reported in the checking of moved variables,
369-
/// so that we don't report report seemingly duplicate errors.
380+
/// so that we don't report seemingly duplicate errors.
370381
moved_error_reported: FxHashSet<Place<'tcx>>,
382+
/// Errors to be reported buffer
383+
errors_buffer: Vec<Diagnostic>,
371384
/// This field keeps track of all the local variables that are declared mut and are mutated.
372385
/// Used for the warning issued by an unused mutable local variable.
373386
used_mut: FxHashSet<Local>,
@@ -1354,13 +1367,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
13541367
debug!("check_for_local_borrow({:?})", borrow);
13551368

13561369
if borrow_of_local_data(&borrow.borrowed_place) {
1357-
self.tcx
1370+
let err = self.tcx
13581371
.cannot_borrow_across_generator_yield(
13591372
self.retrieve_borrow_span(borrow),
13601373
yield_span,
13611374
Origin::Mir,
1362-
)
1363-
.emit();
1375+
);
1376+
1377+
err.buffer(&mut self.errors_buffer);
13641378
}
13651379
}
13661380

‎src/librustc_mir/borrow_check/move_errors.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ enum GroupedMoveError<'tcx> {
5959
}
6060

6161
impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
62-
pub(crate) fn report_move_errors(&self, move_errors: Vec<MoveError<'tcx>>) {
62+
pub(crate) fn report_move_errors(&mut self, move_errors: Vec<MoveError<'tcx>>) {
6363
let grouped_errors = self.group_move_errors(move_errors);
6464
for error in grouped_errors {
6565
self.report(error);
@@ -218,7 +218,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
218218
};
219219
}
220220

221-
fn report(&self, error: GroupedMoveError<'tcx>) {
221+
fn report(&mut self, error: GroupedMoveError<'tcx>) {
222222
let (mut err, err_span) = {
223223
let (span, kind): (Span, &IllegalMoveOriginKind) = match error {
224224
GroupedMoveError::MovesFromMatchPlace { span, ref kind, .. }
@@ -286,7 +286,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
286286
};
287287

288288
self.add_move_hints(error, &mut err, err_span);
289-
err.emit();
289+
err.buffer(&mut self.errors_buffer);
290290
}
291291

292292
fn add_move_hints(

‎src/librustc_mir/borrow_check/mutability_errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
378378
}
379379
}
380380

381-
err.emit();
381+
err.buffer(&mut self.errors_buffer);
382382
}
383383

384384
// Does this place refer to what the user sees as an upvar

‎src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ use rustc::ty::{RegionVid, TyCtxt};
1919
use rustc_data_structures::fx::FxHashSet;
2020
use util::liveness::{self, DefUse, LivenessMode};
2121

22-
crate fn find<'cx, 'gcx: 'tcx, 'tcx: 'cx>(
23-
mir: &'cx Mir<'tcx>,
24-
regioncx: &'cx Rc<RegionInferenceContext<'tcx>>,
25-
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
22+
crate fn find<'tcx>(
23+
mir: &Mir<'tcx>,
24+
regioncx: &Rc<RegionInferenceContext<'tcx>>,
25+
tcx: TyCtxt<'_, '_, 'tcx>,
2626
region_vid: RegionVid,
2727
start_point: Location,
2828
) -> Option<Cause> {

‎src/librustc_mir/borrow_check/nll/mod.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use rustc::infer::InferCtxt;
2323
use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir};
2424
use rustc::ty::{self, RegionKind, RegionVid};
2525
use rustc::util::nodemap::FxHashMap;
26+
use rustc_errors::Diagnostic;
2627
use std::collections::BTreeSet;
2728
use std::fmt::Debug;
2829
use std::env;
@@ -91,6 +92,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
9192
flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'cx, 'gcx, 'tcx>>,
9293
move_data: &MoveData<'tcx>,
9394
borrow_set: &BorrowSet<'tcx>,
95+
errors_buffer: &mut Vec<Diagnostic>,
9496
) -> (
9597
RegionInferenceContext<'tcx>,
9698
Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
@@ -120,6 +122,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
120122
flow_inits,
121123
move_data,
122124
elements,
125+
errors_buffer,
123126
);
124127

125128
if let Some(all_facts) = &mut all_facts {
@@ -190,7 +193,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
190193
});
191194

192195
// Solve the region constraints.
193-
let closure_region_requirements = regioncx.solve(infcx, &mir, def_id);
196+
let closure_region_requirements = regioncx.solve(infcx, &mir, def_id, errors_buffer);
194197

195198
// Dump MIR results into a file, if that is enabled. This let us
196199
// write unit-tests, as well as helping with debugging.
@@ -205,7 +208,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
205208

206209
// We also have a `#[rustc_nll]` annotation that causes us to dump
207210
// information
208-
dump_annotation(infcx, &mir, def_id, &regioncx, &closure_region_requirements);
211+
dump_annotation(infcx, &mir, def_id, &regioncx, &closure_region_requirements, errors_buffer);
209212

210213
(regioncx, polonius_output, closure_region_requirements)
211214
}
@@ -323,6 +326,7 @@ fn dump_annotation<'a, 'gcx, 'tcx>(
323326
mir_def_id: DefId,
324327
regioncx: &RegionInferenceContext,
325328
closure_region_requirements: &Option<ClosureRegionRequirements>,
329+
errors_buffer: &mut Vec<Diagnostic>,
326330
) {
327331
let tcx = infcx.tcx;
328332
let base_def_id = tcx.closure_base_def_id(mir_def_id);
@@ -357,14 +361,15 @@ fn dump_annotation<'a, 'gcx, 'tcx>(
357361
Ok(())
358362
}).unwrap();
359363

360-
err.emit();
364+
err.buffer(errors_buffer);
361365
} else {
362366
let mut err = tcx
363367
.sess
364368
.diagnostic()
365369
.span_note_diag(mir.span, "No external requirements");
366370
regioncx.annotate(&mut err);
367-
err.emit();
371+
372+
err.buffer(errors_buffer);
368373
}
369374
}
370375

‎src/librustc_mir/borrow_check/nll/region_infer/annotation.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use borrow_check::nll::region_infer::RegionInferenceContext;
1919
use borrow_check::nll::universal_regions::DefiningTy;
2020
use rustc_errors::DiagnosticBuilder;
2121

22-
impl<'gcx, 'tcx> RegionInferenceContext<'tcx> {
22+
impl<'tcx> RegionInferenceContext<'tcx> {
2323
/// Write out our state into the `.mir` files.
2424
pub(crate) fn annotate(&self, err: &mut DiagnosticBuilder<'_>) {
2525
match self.universal_regions.defining_ty {

‎src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc::mir::{self, Location, Mir, Place, Rvalue, StatementKind, TerminatorKi
1818
use rustc::ty::RegionVid;
1919
use rustc_data_structures::fx::FxHashSet;
2020
use rustc_data_structures::indexed_vec::IndexVec;
21+
use rustc_errors::Diagnostic;
2122
use std::fmt;
2223
use syntax_pos::Span;
2324

@@ -199,6 +200,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
199200
fr: RegionVid,
200201
outlived_fr: RegionVid,
201202
blame_span: Span,
203+
errors_buffer: &mut Vec<Diagnostic>,
202204
) {
203205
debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
204206

@@ -247,9 +249,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
247249
match category {
248250
ConstraintCategory::AssignmentToUpvar |
249251
ConstraintCategory::CallArgumentToUpvar =>
250-
self.report_closure_error(mir, infcx, mir_def_id, fr, outlived_fr, category, span),
252+
self.report_closure_error(
253+
mir, infcx, mir_def_id, fr, outlived_fr, category, span, errors_buffer),
251254
_ =>
252-
self.report_general_error(mir, infcx, mir_def_id, fr, outlived_fr, category, span),
255+
self.report_general_error(
256+
mir, infcx, mir_def_id, fr, outlived_fr, category, span, errors_buffer),
253257
}
254258
}
255259

@@ -262,18 +266,19 @@ impl<'tcx> RegionInferenceContext<'tcx> {
262266
outlived_fr: RegionVid,
263267
category: &ConstraintCategory,
264268
span: &Span,
269+
errors_buffer: &mut Vec<Diagnostic>,
265270
) {
266271
let fr_name_and_span = self.get_var_name_and_span_for_region(
267272
infcx.tcx, mir, fr);
268273
let outlived_fr_name_and_span = self.get_var_name_and_span_for_region(
269274
infcx.tcx, mir,outlived_fr);
270275

271276
if fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none() {
272-
return self.report_general_error(mir, infcx, mir_def_id, fr, outlived_fr, category,
273-
span);
277+
return self.report_general_error(
278+
mir, infcx, mir_def_id, fr, outlived_fr, category, span, errors_buffer);
274279
}
275280

276-
let diag = &mut infcx.tcx.sess.struct_span_err(
281+
let mut diag = infcx.tcx.sess.struct_span_err(
277282
*span, &format!("borrowed data escapes outside of closure"),
278283
);
279284

@@ -297,7 +302,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
297302
}
298303
}
299304

300-
diag.emit();
305+
diag.buffer(errors_buffer);
301306
}
302307

303308
fn report_general_error(
@@ -309,23 +314,24 @@ impl<'tcx> RegionInferenceContext<'tcx> {
309314
outlived_fr: RegionVid,
310315
category: &ConstraintCategory,
311316
span: &Span,
317+
errors_buffer: &mut Vec<Diagnostic>,
312318
) {
313-
let diag = &mut infcx.tcx.sess.struct_span_err(
319+
let mut diag = infcx.tcx.sess.struct_span_err(
314320
*span, &format!("unsatisfied lifetime constraints"), // FIXME
315321
);
316322

317323
let counter = &mut 1;
318324
let fr_name = self.give_region_a_name(
319-
infcx.tcx, mir, mir_def_id, fr, counter, diag);
325+
infcx.tcx, mir, mir_def_id, fr, counter, &mut diag);
320326
let outlived_fr_name = self.give_region_a_name(
321-
infcx.tcx, mir, mir_def_id, outlived_fr, counter, diag);
327+
infcx.tcx, mir, mir_def_id, outlived_fr, counter, &mut diag);
322328

323329
diag.span_label(*span, format!(
324330
"{} requires that `{}` must outlive `{}`",
325331
category, fr_name, outlived_fr_name,
326332
));
327333

328-
diag.emit();
334+
diag.buffer(errors_buffer);
329335
}
330336

331337
// Find some constraint `X: Y` where:

‎src/librustc_mir/borrow_check/nll/region_infer/mod.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use rustc::util::common;
3030
use rustc_data_structures::graph::scc::Sccs;
3131
use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf};
3232
use rustc_data_structures::indexed_vec::IndexVec;
33+
use rustc_errors::Diagnostic;
3334

3435
use std::rc::Rc;
3536

@@ -360,11 +361,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
360361
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
361362
mir: &Mir<'tcx>,
362363
mir_def_id: DefId,
364+
errors_buffer: &mut Vec<Diagnostic>,
363365
) -> Option<ClosureRegionRequirements<'gcx>> {
364366
common::time(
365367
infcx.tcx.sess,
366368
&format!("solve_nll_region_constraints({:?})", mir_def_id),
367-
|| self.solve_inner(infcx, mir, mir_def_id),
369+
|| self.solve_inner(infcx, mir, mir_def_id, errors_buffer),
368370
)
369371
}
370372

@@ -373,6 +375,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
373375
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
374376
mir: &Mir<'tcx>,
375377
mir_def_id: DefId,
378+
errors_buffer: &mut Vec<Diagnostic>,
376379
) -> Option<ClosureRegionRequirements<'gcx>> {
377380
self.propagate_constraints(mir);
378381

@@ -387,9 +390,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
387390
None
388391
};
389392

390-
self.check_type_tests(infcx, mir, mir_def_id, outlives_requirements.as_mut());
393+
self.check_type_tests(
394+
infcx, mir, mir_def_id, outlives_requirements.as_mut(), errors_buffer);
391395

392-
self.check_universal_regions(infcx, mir, mir_def_id, outlives_requirements.as_mut());
396+
self.check_universal_regions(
397+
infcx, mir, mir_def_id, outlives_requirements.as_mut(), errors_buffer);
393398

394399
let outlives_requirements = outlives_requirements.unwrap_or(vec![]);
395400

@@ -476,6 +481,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
476481
mir: &Mir<'tcx>,
477482
mir_def_id: DefId,
478483
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
484+
errors_buffer: &mut Vec<Diagnostic>,
479485
) {
480486
let tcx = infcx.tcx;
481487

@@ -502,13 +508,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
502508
if let Some(lower_bound_region) = lower_bound_region {
503509
let region_scope_tree = &tcx.region_scope_tree(mir_def_id);
504510
let type_test_span = type_test.locations.span(mir);
505-
infcx.report_generic_bound_failure(
511+
infcx.construct_generic_bound_failure(
506512
region_scope_tree,
507513
type_test_span,
508514
None,
509515
type_test.generic_kind,
510516
lower_bound_region,
511-
);
517+
).buffer(errors_buffer);
512518
} else {
513519
// FIXME. We should handle this case better. It
514520
// indicates that we have e.g. some region variable
@@ -520,10 +526,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
520526
// iterating over the universal regions and reporting
521527
// an error that multiple bounds are required.
522528
let type_test_span = type_test.locations.span(mir);
523-
tcx.sess.span_err(
529+
tcx.sess.struct_span_err(
524530
type_test_span,
525531
&format!("`{}` does not live long enough", type_test.generic_kind,),
526-
);
532+
).buffer(errors_buffer);
527533
}
528534
}
529535
}
@@ -834,6 +840,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
834840
mir: &Mir<'tcx>,
835841
mir_def_id: DefId,
836842
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
843+
errors_buffer: &mut Vec<Diagnostic>,
837844
) {
838845
// The universal regions are always found in a prefix of the
839846
// full list.
@@ -851,6 +858,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
851858
mir_def_id,
852859
fr,
853860
&mut propagated_outlives_requirements,
861+
errors_buffer,
854862
);
855863
}
856864
}
@@ -870,6 +878,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
870878
mir_def_id: DefId,
871879
longer_fr: RegionVid,
872880
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
881+
errors_buffer: &mut Vec<Diagnostic>,
873882
) {
874883
debug!("check_universal_region(fr={:?})", longer_fr);
875884

@@ -924,7 +933,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
924933
// Note: in this case, we use the unapproximated regions
925934
// to report the error. This gives better error messages
926935
// in some cases.
927-
self.report_error(mir, infcx, mir_def_id, longer_fr, shorter_fr, blame_span);
936+
self.report_error(
937+
mir, infcx, mir_def_id, longer_fr, shorter_fr, blame_span, errors_buffer);
928938
}
929939
}
930940
}

‎src/librustc_mir/borrow_check/nll/type_check/mod.rs

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ use std::rc::Rc;
4141
use syntax_pos::{Span, DUMMY_SP};
4242
use transform::{MirPass, MirSource};
4343
use util::liveness::LivenessResults;
44+
use rustc_errors::Diagnostic;
4445

4546
use rustc_data_structures::fx::FxHashSet;
4647
use rustc_data_structures::indexed_vec::Idx;
@@ -102,6 +103,7 @@ mod liveness;
102103
/// constraints for the regions in the types of variables
103104
/// - `flow_inits` -- results of a maybe-init dataflow analysis
104105
/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
106+
/// - `errors_buffer` -- errors are sent here for future reporting
105107
pub(crate) fn type_check<'gcx, 'tcx>(
106108
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
107109
param_env: ty::ParamEnv<'gcx>,
@@ -115,6 +117,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
115117
flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
116118
move_data: &MoveData<'tcx>,
117119
elements: &Rc<RegionValueElements>,
120+
errors_buffer: &mut Vec<Diagnostic>,
118121
) -> MirTypeckRegionConstraints<'tcx> {
119122
let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
120123
let mut constraints = MirTypeckRegionConstraints {
@@ -140,14 +143,13 @@ pub(crate) fn type_check<'gcx, 'tcx>(
140143
&universal_regions.region_bound_pairs,
141144
Some(implicit_region_bound),
142145
Some(&mut borrowck_context),
146+
Some(errors_buffer),
143147
|cx| {
144148
liveness::generate(cx, mir, liveness, flow_inits, move_data);
145-
146149
cx.equate_inputs_and_outputs(mir, mir_def_id, universal_regions);
147150
},
148151
);
149152
}
150-
151153
constraints
152154
}
153155

@@ -159,6 +161,7 @@ fn type_check_internal<'a, 'gcx, 'tcx, F>(
159161
region_bound_pairs: &'a [(ty::Region<'tcx>, GenericKind<'tcx>)],
160162
implicit_region_bound: Option<ty::Region<'tcx>>,
161163
borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>,
164+
errors_buffer: Option<&mut Vec<Diagnostic>>,
162165
mut extra: F,
163166
)
164167
where F: FnMut(&mut TypeChecker<'a, 'gcx, 'tcx>)
@@ -180,7 +183,7 @@ fn type_check_internal<'a, 'gcx, 'tcx, F>(
180183

181184
if !errors_reported {
182185
// if verifier failed, don't do further checks to avoid ICEs
183-
checker.typeck_mir(mir);
186+
checker.typeck_mir(mir, errors_buffer);
184187
}
185188

186189
extra(&mut checker);
@@ -202,7 +205,7 @@ enum FieldAccessError {
202205
/// The sanitize_XYZ methods here take an MIR object and compute its
203206
/// type, calling `span_mirbug` and returning an error type if there
204207
/// is a problem.
205-
struct TypeVerifier<'a, 'b: 'a, 'gcx: 'b + 'tcx, 'tcx: 'b> {
208+
struct TypeVerifier<'a, 'b: 'a, 'gcx: 'tcx, 'tcx: 'b> {
206209
cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>,
207210
mir: &'a Mir<'tcx>,
208211
last_span: Span,
@@ -611,7 +614,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
611614
/// constraints needed for it to be valid and well-typed. Along the
612615
/// way, it accrues region constraints -- these can later be used by
613616
/// NLL region checking.
614-
struct TypeChecker<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
617+
struct TypeChecker<'a, 'gcx: 'tcx, 'tcx: 'a> {
615618
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
616619
param_env: ty::ParamEnv<'gcx>,
617620
last_span: Span,
@@ -1227,7 +1230,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
12271230
}
12281231
}
12291232

1230-
fn check_local(&mut self, mir: &Mir<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>) {
1233+
fn check_local(&mut self,
1234+
mir: &Mir<'tcx>,
1235+
local: Local,
1236+
local_decl: &LocalDecl<'tcx>,
1237+
errors_buffer: &mut Option<&mut Vec<Diagnostic>>)
1238+
{
12311239
match mir.local_kind(local) {
12321240
LocalKind::ReturnPointer | LocalKind::Arg => {
12331241
// return values of normal functions are required to be
@@ -1255,14 +1263,21 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
12551263
// slot or local, so to find all unsized rvalues it is enough
12561264
// to check all temps, return slots and locals.
12571265
if let None = self.reported_errors.replace((ty, span)) {
1258-
span_err!(
1259-
self.tcx().sess,
1260-
span,
1261-
E0161,
1262-
"cannot move a value of type {0}: the size of {0} \
1263-
cannot be statically determined",
1264-
ty
1265-
);
1266+
let mut diag = struct_span_err!(self.tcx().sess,
1267+
span,
1268+
E0161,
1269+
"cannot move a value of type {0}: the size of {0} \
1270+
cannot be statically determined",
1271+
ty);
1272+
if let Some(ref mut errors_buffer) = *errors_buffer {
1273+
diag.buffer(errors_buffer);
1274+
} else {
1275+
// we're allowed to use emit() here because the
1276+
// NLL migration will be turned on (and thus
1277+
// errors will need to be buffered) *only if*
1278+
// errors_buffer is Some.
1279+
diag.emit();
1280+
}
12661281
}
12671282
}
12681283
}
@@ -1742,12 +1757,15 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
17421757
})
17431758
}
17441759

1745-
fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
1760+
fn typeck_mir(&mut self,
1761+
mir: &Mir<'tcx>,
1762+
mut errors_buffer: Option<&mut Vec<Diagnostic>>)
1763+
{
17461764
self.last_span = mir.span;
17471765
debug!("run_on_mir: {:?}", mir.span);
17481766

17491767
for (local, local_decl) in mir.local_decls.iter_enumerated() {
1750-
self.check_local(mir, local, local_decl);
1768+
self.check_local(mir, local, local_decl, &mut errors_buffer);
17511769
}
17521770

17531771
for (block, block_data) in mir.basic_blocks().iter_enumerated() {
@@ -1812,7 +1830,7 @@ impl MirPass for TypeckMir {
18121830

18131831
let param_env = tcx.param_env(def_id);
18141832
tcx.infer_ctxt().enter(|infcx| {
1815-
type_check_internal(&infcx, def_id, param_env, mir, &[], None, None, |_| ());
1833+
type_check_internal(&infcx, def_id, param_env, mir, &[], None, None, None, |_| ());
18161834

18171835
// For verification purposes, we just ignore the resulting
18181836
// region constraint sets. Not our problem. =)

‎src/librustc_mir/dataflow/graphviz.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ pub trait MirWithFlowState<'tcx> {
3434
fn flow_state(&self) -> &DataflowState<Self::BD>;
3535
}
3636

37-
impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD>
38-
where 'tcx: 'a, BD: BitDenotation
37+
impl<'a, 'tcx, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD>
38+
where BD: BitDenotation
3939
{
4040
type BD = BD;
4141
fn node_id(&self) -> NodeId { self.node_id }

‎src/librustc_mir/dataflow/impls/borrows.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
5353
_nonlexical_regioncx: Rc<RegionInferenceContext<'tcx>>,
5454
}
5555

56-
fn precompute_borrows_out_of_scope<'a, 'tcx>(
57-
mir: &'a Mir<'tcx>,
56+
fn precompute_borrows_out_of_scope<'tcx>(
57+
mir: &Mir<'tcx>,
5858
regioncx: &Rc<RegionInferenceContext<'tcx>>,
5959
borrows_out_of_scope_at_location: &mut FxHashMap<Location, Vec<BorrowIndex>>,
6060
borrow_index: BorrowIndex,

0 commit comments

Comments
 (0)
Please sign in to comment.