Skip to content

Commit fbefa2e

Browse files
committed
merge diags module into diagnostics
it's a more natural place for diagnostics-related structures and functions
1 parent 4107a3c commit fbefa2e

File tree

3 files changed

+142
-149
lines changed

3 files changed

+142
-149
lines changed

compiler/rustc_borrowck/src/diagnostics/mod.rs

+136-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
//! Borrow checker diagnostics.
22
3+
use std::collections::BTreeMap;
4+
35
use rustc_abi::{FieldIdx, VariantIdx};
6+
use rustc_data_structures::fx::FxIndexMap;
47
use rustc_errors::{Applicability, Diag, MultiSpan};
58
use rustc_hir::def::{CtorKind, Namespace};
69
use rustc_hir::{self as hir, CoroutineKind, LangItem};
@@ -17,10 +20,10 @@ use rustc_middle::mir::{
1720
use rustc_middle::ty::print::Print;
1821
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
1922
use rustc_middle::util::{CallDesugaringKind, call_kind};
20-
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
23+
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult, MoveOutIndex};
2124
use rustc_span::def_id::LocalDefId;
2225
use rustc_span::source_map::Spanned;
23-
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
26+
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
2427
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
2528
use rustc_trait_selection::infer::InferCtxtExt;
2629
use rustc_trait_selection::traits::{
@@ -68,6 +71,137 @@ pub(super) struct DescribePlaceOpt {
6871

6972
pub(super) struct IncludingTupleField(pub(super) bool);
7073

74+
enum BufferedDiag<'infcx> {
75+
Error(Diag<'infcx>),
76+
NonError(Diag<'infcx, ()>),
77+
}
78+
79+
impl<'infcx> BufferedDiag<'infcx> {
80+
fn sort_span(&self) -> Span {
81+
match self {
82+
BufferedDiag::Error(diag) => diag.sort_span,
83+
BufferedDiag::NonError(diag) => diag.sort_span,
84+
}
85+
}
86+
}
87+
88+
pub(crate) struct BorrowckDiags<'infcx, 'tcx> {
89+
/// This field keeps track of move errors that are to be reported for given move indices.
90+
///
91+
/// There are situations where many errors can be reported for a single move out (see
92+
/// #53807) and we want only the best of those errors.
93+
///
94+
/// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the
95+
/// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of
96+
/// the `Place` of the previous most diagnostic. This happens instead of buffering the
97+
/// error. Once all move errors have been reported, any diagnostics in this map are added
98+
/// to the buffer to be emitted.
99+
///
100+
/// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary
101+
/// when errors in the map are being re-added to the error buffer so that errors with the
102+
/// same primary span come out in a consistent order.
103+
buffered_move_errors: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, Diag<'infcx>)>,
104+
105+
buffered_mut_errors: FxIndexMap<Span, (Diag<'infcx>, usize)>,
106+
107+
/// Buffer of diagnostics to be reported. A mixture of error and non-error diagnostics.
108+
buffered_diags: Vec<BufferedDiag<'infcx>>,
109+
}
110+
111+
impl<'infcx, 'tcx> BorrowckDiags<'infcx, 'tcx> {
112+
pub(crate) fn new() -> Self {
113+
BorrowckDiags {
114+
buffered_move_errors: BTreeMap::new(),
115+
buffered_mut_errors: Default::default(),
116+
buffered_diags: Default::default(),
117+
}
118+
}
119+
120+
pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) {
121+
self.buffered_diags.push(BufferedDiag::Error(diag));
122+
}
123+
124+
pub(crate) fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) {
125+
self.buffered_diags.push(BufferedDiag::NonError(diag));
126+
}
127+
}
128+
129+
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
130+
pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) {
131+
self.diags.buffer_error(diag);
132+
}
133+
134+
pub(crate) fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) {
135+
self.diags.buffer_non_error(diag);
136+
}
137+
138+
pub(crate) fn buffer_move_error(
139+
&mut self,
140+
move_out_indices: Vec<MoveOutIndex>,
141+
place_and_err: (PlaceRef<'tcx>, Diag<'infcx>),
142+
) -> bool {
143+
if let Some((_, diag)) =
144+
self.diags.buffered_move_errors.insert(move_out_indices, place_and_err)
145+
{
146+
// Cancel the old diagnostic so we don't ICE
147+
diag.cancel();
148+
false
149+
} else {
150+
true
151+
}
152+
}
153+
154+
pub(crate) fn get_buffered_mut_error(&mut self, span: Span) -> Option<(Diag<'infcx>, usize)> {
155+
// FIXME(#120456) - is `swap_remove` correct?
156+
self.diags.buffered_mut_errors.swap_remove(&span)
157+
}
158+
159+
pub(crate) fn buffer_mut_error(&mut self, span: Span, diag: Diag<'infcx>, count: usize) {
160+
self.diags.buffered_mut_errors.insert(span, (diag, count));
161+
}
162+
163+
pub(crate) fn emit_errors(&mut self) -> Option<ErrorGuaranteed> {
164+
let mut res = self.infcx.tainted_by_errors();
165+
166+
// Buffer any move errors that we collected and de-duplicated.
167+
for (_, (_, diag)) in std::mem::take(&mut self.diags.buffered_move_errors) {
168+
// We have already set tainted for this error, so just buffer it.
169+
self.diags.buffer_error(diag);
170+
}
171+
for (_, (mut diag, count)) in std::mem::take(&mut self.diags.buffered_mut_errors) {
172+
if count > 10 {
173+
#[allow(rustc::diagnostic_outside_of_impl)]
174+
#[allow(rustc::untranslatable_diagnostic)]
175+
diag.note(format!("...and {} other attempted mutable borrows", count - 10));
176+
}
177+
self.diags.buffer_error(diag);
178+
}
179+
180+
if !self.diags.buffered_diags.is_empty() {
181+
self.diags.buffered_diags.sort_by_key(|buffered_diag| buffered_diag.sort_span());
182+
for buffered_diag in self.diags.buffered_diags.drain(..) {
183+
match buffered_diag {
184+
BufferedDiag::Error(diag) => res = Some(diag.emit()),
185+
BufferedDiag::NonError(diag) => diag.emit(),
186+
}
187+
}
188+
}
189+
190+
res
191+
}
192+
193+
pub(crate) fn has_buffered_diags(&self) -> bool {
194+
self.diags.buffered_diags.is_empty()
195+
}
196+
197+
pub(crate) fn has_move_error(
198+
&self,
199+
move_out_indices: &[MoveOutIndex],
200+
) -> Option<&(PlaceRef<'tcx>, Diag<'infcx>)> {
201+
self.diags.buffered_move_errors.get(move_out_indices)
202+
}
203+
}
204+
71205
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
72206
/// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure
73207
/// is moved after being invoked.

compiler/rustc_borrowck/src/lib.rs

+4-145
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,13 @@
1616
// tidy-alphabetical-end
1717

1818
use std::cell::RefCell;
19-
use std::collections::BTreeMap;
2019
use std::marker::PhantomData;
2120
use std::ops::Deref;
2221

22+
use diagnostics::BorrowckDiags;
2323
use rustc_abi::FieldIdx;
2424
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
2525
use rustc_data_structures::graph::dominators::Dominators;
26-
use rustc_errors::Diag;
2726
use rustc_hir as hir;
2827
use rustc_hir::def_id::LocalDefId;
2928
use rustc_index::bit_set::{BitSet, MixedBitSet};
@@ -41,7 +40,7 @@ use rustc_mir_dataflow::impls::{
4140
EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
4241
};
4342
use rustc_mir_dataflow::move_paths::{
44-
InitIndex, InitLocation, LookupResult, MoveData, MoveOutIndex, MovePathIndex,
43+
InitIndex, InitLocation, LookupResult, MoveData, MovePathIndex,
4544
};
4645
use rustc_mir_dataflow::{Analysis, EntryStates, Results, ResultsVisitor, visit_results};
4746
use rustc_session::lint::builtin::UNUSED_MUT;
@@ -217,7 +216,7 @@ fn do_mir_borrowck<'tcx>(
217216

218217
// We also have a `#[rustc_regions]` annotation that causes us to dump
219218
// information.
220-
let diags = &mut diags::BorrowckDiags::new();
219+
let diags = &mut BorrowckDiags::new();
221220
nll::dump_annotation(&infcx, body, &regioncx, &opt_closure_req, &opaque_type_values, diags);
222221

223222
let movable_coroutine =
@@ -566,7 +565,7 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
566565
/// Results of Polonius analysis.
567566
polonius_output: Option<Box<PoloniusOutput>>,
568567

569-
diags: &'a mut diags::BorrowckDiags<'infcx, 'tcx>,
568+
diags: &'a mut BorrowckDiags<'infcx, 'tcx>,
570569
move_errors: Vec<MoveError<'tcx>>,
571570
}
572571

@@ -2399,146 +2398,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
23992398
}
24002399
}
24012400

2402-
mod diags {
2403-
use rustc_errors::ErrorGuaranteed;
2404-
2405-
use super::*;
2406-
2407-
enum BufferedDiag<'infcx> {
2408-
Error(Diag<'infcx>),
2409-
NonError(Diag<'infcx, ()>),
2410-
}
2411-
2412-
impl<'infcx> BufferedDiag<'infcx> {
2413-
fn sort_span(&self) -> Span {
2414-
match self {
2415-
BufferedDiag::Error(diag) => diag.sort_span,
2416-
BufferedDiag::NonError(diag) => diag.sort_span,
2417-
}
2418-
}
2419-
}
2420-
2421-
pub(crate) struct BorrowckDiags<'infcx, 'tcx> {
2422-
/// This field keeps track of move errors that are to be reported for given move indices.
2423-
///
2424-
/// There are situations where many errors can be reported for a single move out (see
2425-
/// #53807) and we want only the best of those errors.
2426-
///
2427-
/// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the
2428-
/// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of
2429-
/// the `Place` of the previous most diagnostic. This happens instead of buffering the
2430-
/// error. Once all move errors have been reported, any diagnostics in this map are added
2431-
/// to the buffer to be emitted.
2432-
///
2433-
/// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary
2434-
/// when errors in the map are being re-added to the error buffer so that errors with the
2435-
/// same primary span come out in a consistent order.
2436-
buffered_move_errors: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, Diag<'infcx>)>,
2437-
2438-
buffered_mut_errors: FxIndexMap<Span, (Diag<'infcx>, usize)>,
2439-
2440-
/// Buffer of diagnostics to be reported. A mixture of error and non-error diagnostics.
2441-
buffered_diags: Vec<BufferedDiag<'infcx>>,
2442-
}
2443-
2444-
impl<'infcx, 'tcx> BorrowckDiags<'infcx, 'tcx> {
2445-
pub(crate) fn new() -> Self {
2446-
BorrowckDiags {
2447-
buffered_move_errors: BTreeMap::new(),
2448-
buffered_mut_errors: Default::default(),
2449-
buffered_diags: Default::default(),
2450-
}
2451-
}
2452-
2453-
pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) {
2454-
self.buffered_diags.push(BufferedDiag::Error(diag));
2455-
}
2456-
2457-
pub(crate) fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) {
2458-
self.buffered_diags.push(BufferedDiag::NonError(diag));
2459-
}
2460-
}
2461-
2462-
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
2463-
pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) {
2464-
self.diags.buffer_error(diag);
2465-
}
2466-
2467-
pub(crate) fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) {
2468-
self.diags.buffer_non_error(diag);
2469-
}
2470-
2471-
pub(crate) fn buffer_move_error(
2472-
&mut self,
2473-
move_out_indices: Vec<MoveOutIndex>,
2474-
place_and_err: (PlaceRef<'tcx>, Diag<'infcx>),
2475-
) -> bool {
2476-
if let Some((_, diag)) =
2477-
self.diags.buffered_move_errors.insert(move_out_indices, place_and_err)
2478-
{
2479-
// Cancel the old diagnostic so we don't ICE
2480-
diag.cancel();
2481-
false
2482-
} else {
2483-
true
2484-
}
2485-
}
2486-
2487-
pub(crate) fn get_buffered_mut_error(
2488-
&mut self,
2489-
span: Span,
2490-
) -> Option<(Diag<'infcx>, usize)> {
2491-
// FIXME(#120456) - is `swap_remove` correct?
2492-
self.diags.buffered_mut_errors.swap_remove(&span)
2493-
}
2494-
2495-
pub(crate) fn buffer_mut_error(&mut self, span: Span, diag: Diag<'infcx>, count: usize) {
2496-
self.diags.buffered_mut_errors.insert(span, (diag, count));
2497-
}
2498-
2499-
pub(crate) fn emit_errors(&mut self) -> Option<ErrorGuaranteed> {
2500-
let mut res = self.infcx.tainted_by_errors();
2501-
2502-
// Buffer any move errors that we collected and de-duplicated.
2503-
for (_, (_, diag)) in std::mem::take(&mut self.diags.buffered_move_errors) {
2504-
// We have already set tainted for this error, so just buffer it.
2505-
self.diags.buffer_error(diag);
2506-
}
2507-
for (_, (mut diag, count)) in std::mem::take(&mut self.diags.buffered_mut_errors) {
2508-
if count > 10 {
2509-
#[allow(rustc::diagnostic_outside_of_impl)]
2510-
#[allow(rustc::untranslatable_diagnostic)]
2511-
diag.note(format!("...and {} other attempted mutable borrows", count - 10));
2512-
}
2513-
self.diags.buffer_error(diag);
2514-
}
2515-
2516-
if !self.diags.buffered_diags.is_empty() {
2517-
self.diags.buffered_diags.sort_by_key(|buffered_diag| buffered_diag.sort_span());
2518-
for buffered_diag in self.diags.buffered_diags.drain(..) {
2519-
match buffered_diag {
2520-
BufferedDiag::Error(diag) => res = Some(diag.emit()),
2521-
BufferedDiag::NonError(diag) => diag.emit(),
2522-
}
2523-
}
2524-
}
2525-
2526-
res
2527-
}
2528-
2529-
pub(crate) fn has_buffered_diags(&self) -> bool {
2530-
self.diags.buffered_diags.is_empty()
2531-
}
2532-
2533-
pub(crate) fn has_move_error(
2534-
&self,
2535-
move_out_indices: &[MoveOutIndex],
2536-
) -> Option<&(PlaceRef<'tcx>, Diag<'infcx>)> {
2537-
self.diags.buffered_move_errors.get(move_out_indices)
2538-
}
2539-
}
2540-
}
2541-
25422401
/// The degree of overlap between 2 places for borrow-checking.
25432402
enum Overlap {
25442403
/// The places might partially overlap - in this case, we give

compiler/rustc_borrowck/src/nll.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use tracing::{debug, instrument};
2626

2727
use crate::borrow_set::BorrowSet;
2828
use crate::consumers::ConsumerOptions;
29-
use crate::diagnostics::RegionErrors;
29+
use crate::diagnostics::{BorrowckDiags, RegionErrors};
3030
use crate::polonius::LocalizedOutlivesConstraintSet;
3131
use crate::polonius::legacy::{AllFacts, AllFactsExt, LocationTable, PoloniusOutput};
3232
use crate::region_infer::RegionInferenceContext;
@@ -298,7 +298,7 @@ pub(super) fn dump_annotation<'tcx, 'infcx>(
298298
regioncx: &RegionInferenceContext<'tcx>,
299299
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
300300
opaque_type_values: &FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
301-
diags: &mut crate::diags::BorrowckDiags<'infcx, 'tcx>,
301+
diags: &mut BorrowckDiags<'infcx, 'tcx>,
302302
) {
303303
let tcx = infcx.tcx;
304304
let base_def_id = tcx.typeck_root_def_id(body.source.def_id());

0 commit comments

Comments
 (0)