Skip to content

Commit 5fd824d

Browse files
committed
Remove BorrowckErrors::tainted_by_errors.
`BorrowckErrors` stores a mix of error and non-error diags in `buffered`. As a result, it downgrades `DiagnosticBuilder`s to `Diagnostic`s, losing the emission guarantees, and so has to use a `tainted_by_errors` field to record whether an error has occurred. This commit splits `buffered` into `buffered_errors` and `buffered_non_errors`, keeping them as `DiagnosticBuilder`s and preserving the emission guarantees. This also requires fixing a bunch of incorrect lifetimes on `DiagnosticBuilder` use points.
1 parent 3a02ebc commit 5fd824d

File tree

4 files changed

+66
-59
lines changed

4 files changed

+66
-59
lines changed

compiler/rustc_borrowck/src/borrowck_errors.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
130130
noun_old: &str,
131131
old_opt_via: &str,
132132
previous_end_span: Option<Span>,
133-
) -> DiagnosticBuilder<'cx> {
133+
) -> DiagnosticBuilder<'tcx> {
134134
let mut err = struct_span_code_err!(
135135
self.dcx(),
136136
new_loan_span,
@@ -162,7 +162,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
162162
old_opt_via: &str,
163163
previous_end_span: Option<Span>,
164164
second_borrow_desc: &str,
165-
) -> DiagnosticBuilder<'cx> {
165+
) -> DiagnosticBuilder<'tcx> {
166166
let mut err = struct_span_code_err!(
167167
self.dcx(),
168168
new_loan_span,
@@ -194,7 +194,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
194194
kind_old: &str,
195195
msg_old: &str,
196196
old_load_end_span: Option<Span>,
197-
) -> DiagnosticBuilder<'cx> {
197+
) -> DiagnosticBuilder<'tcx> {
198198
let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") };
199199
let mut err = struct_span_code_err!(
200200
self.dcx(),
@@ -235,7 +235,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
235235
span: Span,
236236
borrow_span: Span,
237237
desc: &str,
238-
) -> DiagnosticBuilder<'cx> {
238+
) -> DiagnosticBuilder<'tcx> {
239239
struct_span_code_err!(
240240
self.dcx(),
241241
span,
@@ -252,7 +252,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
252252
span: Span,
253253
desc: &str,
254254
is_arg: bool,
255-
) -> DiagnosticBuilder<'cx> {
255+
) -> DiagnosticBuilder<'tcx> {
256256
let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" };
257257
struct_span_code_err!(self.dcx(), span, E0384, "cannot assign {} {}", msg, desc)
258258
}
@@ -265,7 +265,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
265265
&self,
266266
move_from_span: Span,
267267
move_from_desc: &str,
268-
) -> DiagnosticBuilder<'cx> {
268+
) -> DiagnosticBuilder<'tcx> {
269269
struct_span_code_err!(
270270
self.dcx(),
271271
move_from_span,
@@ -283,7 +283,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
283283
move_from_span: Span,
284284
ty: Ty<'_>,
285285
is_index: Option<bool>,
286-
) -> DiagnosticBuilder<'cx> {
286+
) -> DiagnosticBuilder<'tcx> {
287287
let type_name = match (&ty.kind(), is_index) {
288288
(&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array",
289289
(&ty::Slice(_), _) => "slice",
@@ -304,7 +304,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
304304
&self,
305305
move_from_span: Span,
306306
container_ty: Ty<'_>,
307-
) -> DiagnosticBuilder<'cx> {
307+
) -> DiagnosticBuilder<'tcx> {
308308
struct_span_code_err!(
309309
self.dcx(),
310310
move_from_span,

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
327327
&mut self,
328328
mpi: MovePathIndex,
329329
move_span: Span,
330-
err: &mut DiagnosticBuilder<'_>,
330+
err: &mut DiagnosticBuilder<'tcx>,
331331
in_pattern: &mut bool,
332332
move_spans: UseSpans<'_>,
333333
) {
@@ -486,7 +486,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
486486
desired_action: InitializationRequiringAction,
487487
span: Span,
488488
use_spans: UseSpans<'tcx>,
489-
) -> DiagnosticBuilder<'cx> {
489+
) -> DiagnosticBuilder<'tcx> {
490490
// We need all statements in the body where the binding was assigned to later find all
491491
// the branching code paths where the binding *wasn't* assigned to.
492492
let inits = &self.move_data.init_path_map[mpi];
@@ -880,7 +880,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
880880
location: Location,
881881
(place, _span): (Place<'tcx>, Span),
882882
borrow: &BorrowData<'tcx>,
883-
) -> DiagnosticBuilder<'cx> {
883+
) -> DiagnosticBuilder<'tcx> {
884884
let borrow_spans = self.retrieve_borrow_spans(borrow);
885885
let borrow_span = borrow_spans.args_or_use();
886886

@@ -930,7 +930,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
930930
(place, span): (Place<'tcx>, Span),
931931
gen_borrow_kind: BorrowKind,
932932
issued_borrow: &BorrowData<'tcx>,
933-
) -> DiagnosticBuilder<'cx> {
933+
) -> DiagnosticBuilder<'tcx> {
934934
let issued_spans = self.retrieve_borrow_spans(issued_borrow);
935935
let issued_span = issued_spans.args_or_use();
936936

@@ -2129,7 +2129,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
21292129
drop_span: Span,
21302130
borrow_spans: UseSpans<'tcx>,
21312131
explanation: BorrowExplanation<'tcx>,
2132-
) -> DiagnosticBuilder<'cx> {
2132+
) -> DiagnosticBuilder<'tcx> {
21332133
debug!(
21342134
"report_local_value_does_not_live_long_enough(\
21352135
{:?}, {:?}, {:?}, {:?}, {:?}\
@@ -2304,7 +2304,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
23042304
&mut self,
23052305
drop_span: Span,
23062306
borrow_span: Span,
2307-
) -> DiagnosticBuilder<'cx> {
2307+
) -> DiagnosticBuilder<'tcx> {
23082308
debug!(
23092309
"report_thread_local_value_does_not_live_long_enough(\
23102310
{:?}, {:?}\
@@ -2329,7 +2329,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
23292329
borrow_spans: UseSpans<'tcx>,
23302330
proper_span: Span,
23312331
explanation: BorrowExplanation<'tcx>,
2332-
) -> DiagnosticBuilder<'cx> {
2332+
) -> DiagnosticBuilder<'tcx> {
23332333
if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } =
23342334
explanation
23352335
{
@@ -2496,7 +2496,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
24962496
return_span: Span,
24972497
category: ConstraintCategory<'tcx>,
24982498
opt_place_desc: Option<&String>,
2499-
) -> Option<DiagnosticBuilder<'cx>> {
2499+
) -> Option<DiagnosticBuilder<'tcx>> {
25002500
let return_kind = match category {
25012501
ConstraintCategory::Return(_) => "return",
25022502
ConstraintCategory::Yield => "yield",
@@ -2591,7 +2591,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
25912591
constraint_span: Span,
25922592
captured_var: &str,
25932593
scope: &str,
2594-
) -> DiagnosticBuilder<'cx> {
2594+
) -> DiagnosticBuilder<'tcx> {
25952595
let tcx = self.infcx.tcx;
25962596
let args_span = use_span.args_or_use();
25972597

@@ -2699,7 +2699,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
26992699
upvar_span: Span,
27002700
upvar_name: Symbol,
27012701
escape_span: Span,
2702-
) -> DiagnosticBuilder<'cx> {
2702+
) -> DiagnosticBuilder<'tcx> {
27032703
let tcx = self.infcx.tcx;
27042704

27052705
let escapes_from = tcx.def_descr(self.mir_def_id().to_def_id());

compiler/rustc_borrowck/src/diagnostics/move_errors.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
288288
&mut self,
289289
place: Place<'tcx>,
290290
span: Span,
291-
) -> DiagnosticBuilder<'a> {
291+
) -> DiagnosticBuilder<'tcx> {
292292
let description = if place.projection.len() == 1 {
293293
format!("static item {}", self.describe_any_place(place.as_ref()))
294294
} else {
@@ -310,7 +310,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
310310
deref_target_place: Place<'tcx>,
311311
span: Span,
312312
use_spans: Option<UseSpans<'tcx>>,
313-
) -> DiagnosticBuilder<'a> {
313+
) -> DiagnosticBuilder<'tcx> {
314314
// Inspect the type of the content behind the
315315
// borrow to provide feedback about why this
316316
// was a move rather than a copy.

compiler/rustc_borrowck/src/lib.rs

Lines changed: 46 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ extern crate tracing;
1919

2020
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
2121
use rustc_data_structures::graph::dominators::Dominators;
22-
use rustc_errors::{Diagnostic, DiagnosticBuilder};
22+
use rustc_errors::DiagnosticBuilder;
2323
use rustc_hir as hir;
2424
use rustc_hir::def_id::LocalDefId;
2525
use rustc_index::bit_set::{BitSet, ChunkedBitSet};
@@ -173,7 +173,7 @@ fn do_mir_borrowck<'tcx>(
173173
}
174174
}
175175

176-
let mut errors = error::BorrowckErrors::new(infcx.tcx);
176+
let mut errors = error::BorrowckErrors::new();
177177

178178
// Gather the upvars of a closure, if any.
179179
if let Some(e) = input_body.tainted_by_errors {
@@ -2124,7 +2124,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
21242124
| WriteKind::MutableBorrow(BorrowKind::Fake),
21252125
) => {
21262126
if self.is_mutable(place.as_ref(), is_local_mutation_allowed).is_err()
2127-
&& !self.has_buffered_errors()
2127+
&& !self.has_buffered_diags()
21282128
{
21292129
// rust-lang/rust#46908: In pure NLL mode this code path should be
21302130
// unreachable, but we use `span_delayed_bug` because we can hit this when
@@ -2387,12 +2387,25 @@ mod error {
23872387

23882388
use super::*;
23892389

2390+
enum BufferedDiag<'tcx> {
2391+
Error(DiagnosticBuilder<'tcx>),
2392+
NonError(DiagnosticBuilder<'tcx, ()>),
2393+
}
2394+
2395+
impl<'tcx> BufferedDiag<'tcx> {
2396+
fn sort_span(&self) -> Span {
2397+
match self {
2398+
BufferedDiag::Error(diag) => diag.sort_span,
2399+
BufferedDiag::NonError(diag) => diag.sort_span,
2400+
}
2401+
}
2402+
}
2403+
23902404
pub struct BorrowckErrors<'tcx> {
2391-
tcx: TyCtxt<'tcx>,
23922405
/// This field keeps track of move errors that are to be reported for given move indices.
23932406
///
2394-
/// There are situations where many errors can be reported for a single move out (see #53807)
2395-
/// and we want only the best of those errors.
2407+
/// There are situations where many errors can be reported for a single move out (see
2408+
/// #53807) and we want only the best of those errors.
23962409
///
23972410
/// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the
23982411
/// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of
@@ -2405,46 +2418,37 @@ mod error {
24052418
/// same primary span come out in a consistent order.
24062419
buffered_move_errors:
24072420
BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)>,
2421+
24082422
buffered_mut_errors: FxIndexMap<Span, (DiagnosticBuilder<'tcx>, usize)>,
2409-
/// Buffer of diagnostics to be reported. Uses `Diagnostic` rather than `DiagnosticBuilder`
2410-
/// because it has a mixture of error diagnostics and non-error diagnostics.
2411-
buffered: Vec<Diagnostic>,
2412-
/// Set to Some if we emit an error during borrowck
2413-
tainted_by_errors: Option<ErrorGuaranteed>,
2423+
2424+
/// Buffer of diagnostics to be reported. A mixture of error and non-error diagnostics.
2425+
buffered_diags: Vec<BufferedDiag<'tcx>>,
24142426
}
24152427

24162428
impl<'tcx> BorrowckErrors<'tcx> {
2417-
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
2429+
pub fn new() -> Self {
24182430
BorrowckErrors {
2419-
tcx,
24202431
buffered_move_errors: BTreeMap::new(),
24212432
buffered_mut_errors: Default::default(),
2422-
buffered: Default::default(),
2423-
tainted_by_errors: None,
2433+
buffered_diags: Default::default(),
24242434
}
24252435
}
24262436

2427-
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) {
2428-
if let None = self.tainted_by_errors {
2429-
self.tainted_by_errors = Some(self.tcx.dcx().span_delayed_bug(
2430-
t.span.clone_ignoring_labels(),
2431-
"diagnostic buffered but not emitted",
2432-
))
2433-
}
2434-
self.buffered.push(t.into_diagnostic());
2437+
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'tcx>) {
2438+
self.buffered_diags.push(BufferedDiag::Error(t));
24352439
}
24362440

2437-
pub fn buffer_non_error(&mut self, t: DiagnosticBuilder<'_, ()>) {
2438-
self.buffered.push(t.into_diagnostic());
2441+
pub fn buffer_non_error(&mut self, t: DiagnosticBuilder<'tcx, ()>) {
2442+
self.buffered_diags.push(BufferedDiag::NonError(t));
24392443
}
24402444
}
24412445

24422446
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
2443-
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) {
2447+
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'tcx>) {
24442448
self.errors.buffer_error(t);
24452449
}
24462450

2447-
pub fn buffer_non_error(&mut self, t: DiagnosticBuilder<'_, ()>) {
2451+
pub fn buffer_non_error(&mut self, t: DiagnosticBuilder<'tcx, ()>) {
24482452
self.errors.buffer_non_error(t);
24492453
}
24502454

@@ -2476,38 +2480,41 @@ mod error {
24762480
}
24772481

24782482
pub fn emit_errors(&mut self) -> Option<ErrorGuaranteed> {
2483+
let mut res = None;
2484+
24792485
// Buffer any move errors that we collected and de-duplicated.
24802486
for (_, (_, diag)) in std::mem::take(&mut self.errors.buffered_move_errors) {
24812487
// We have already set tainted for this error, so just buffer it.
2482-
self.errors.buffered.push(diag.into_diagnostic());
2488+
self.errors.buffered_diags.push(BufferedDiag::Error(diag));
24832489
}
24842490
for (_, (mut diag, count)) in std::mem::take(&mut self.errors.buffered_mut_errors) {
24852491
if count > 10 {
24862492
diag.note(format!("...and {} other attempted mutable borrows", count - 10));
24872493
}
2488-
self.errors.buffered.push(diag.into_diagnostic());
2494+
self.errors.buffered_diags.push(BufferedDiag::Error(diag));
24892495
}
24902496

2491-
if !self.errors.buffered.is_empty() {
2492-
self.errors.buffered.sort_by_key(|diag| diag.sort_span);
2493-
2494-
let dcx = self.dcx();
2495-
for diag in self.errors.buffered.drain(..) {
2496-
dcx.emit_diagnostic(diag);
2497+
if !self.errors.buffered_diags.is_empty() {
2498+
self.errors.buffered_diags.sort_by_key(|buffered_diag| buffered_diag.sort_span());
2499+
for buffered_diag in self.errors.buffered_diags.drain(..) {
2500+
match buffered_diag {
2501+
BufferedDiag::Error(diag) => res = Some(diag.emit()),
2502+
BufferedDiag::NonError(diag) => diag.emit(),
2503+
}
24972504
}
24982505
}
24992506

2500-
self.errors.tainted_by_errors
2507+
res
25012508
}
25022509

2503-
pub fn has_buffered_errors(&self) -> bool {
2504-
self.errors.buffered.is_empty()
2510+
pub(crate) fn has_buffered_diags(&self) -> bool {
2511+
self.errors.buffered_diags.is_empty()
25052512
}
25062513

25072514
pub fn has_move_error(
25082515
&self,
25092516
move_out_indices: &[MoveOutIndex],
2510-
) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'cx>)> {
2517+
) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)> {
25112518
self.errors.buffered_move_errors.get(move_out_indices)
25122519
}
25132520
}

0 commit comments

Comments
 (0)