diff options
| author | Rémy Rakic <remy.rakic+github@gmail.com> | 2024-12-30 00:56:14 +0000 |
|---|---|---|
| committer | Rémy Rakic <remy.rakic+github@gmail.com> | 2024-12-30 06:51:16 +0000 |
| commit | fbefa2e26722540c7641cc5c0ba8e29b243d8a02 (patch) | |
| tree | 2ff8bbe2c1fae9f2c1b9cab428010f2e908d6c0c | |
| parent | 4107a3ceb40a9f64e95004662bb0e5e74b9b6879 (diff) | |
| download | rust-fbefa2e26722540c7641cc5c0ba8e29b243d8a02.tar.gz rust-fbefa2e26722540c7641cc5c0ba8e29b243d8a02.zip | |
merge `diags` module into `diagnostics`
it's a more natural place for diagnostics-related structures and functions
| -rw-r--r-- | compiler/rustc_borrowck/src/diagnostics/mod.rs | 138 | ||||
| -rw-r--r-- | compiler/rustc_borrowck/src/lib.rs | 149 | ||||
| -rw-r--r-- | compiler/rustc_borrowck/src/nll.rs | 4 |
3 files changed, 142 insertions, 149 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 67be6ecdeb3..c82f5973016 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1,6 +1,9 @@ //! Borrow checker diagnostics. +use std::collections::BTreeMap; + use rustc_abi::{FieldIdx, VariantIdx}; +use rustc_data_structures::fx::FxIndexMap; use rustc_errors::{Applicability, Diag, MultiSpan}; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::{self as hir, CoroutineKind, LangItem}; @@ -17,10 +20,10 @@ use rustc_middle::mir::{ use rustc_middle::ty::print::Print; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::util::{CallDesugaringKind, call_kind}; -use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult}; +use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult, MoveOutIndex}; use rustc_span::def_id::LocalDefId; use rustc_span::source_map::Spanned; -use rustc_span::{DUMMY_SP, Span, Symbol, sym}; +use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{ @@ -68,6 +71,137 @@ pub(super) struct DescribePlaceOpt { pub(super) struct IncludingTupleField(pub(super) bool); +enum BufferedDiag<'infcx> { + Error(Diag<'infcx>), + NonError(Diag<'infcx, ()>), +} + +impl<'infcx> BufferedDiag<'infcx> { + fn sort_span(&self) -> Span { + match self { + BufferedDiag::Error(diag) => diag.sort_span, + BufferedDiag::NonError(diag) => diag.sort_span, + } + } +} + +pub(crate) struct BorrowckDiags<'infcx, 'tcx> { + /// This field keeps track of move errors that are to be reported for given move indices. + /// + /// There are situations where many errors can be reported for a single move out (see + /// #53807) and we want only the best of those errors. + /// + /// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the + /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of + /// the `Place` of the previous most diagnostic. This happens instead of buffering the + /// error. Once all move errors have been reported, any diagnostics in this map are added + /// to the buffer to be emitted. + /// + /// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary + /// when errors in the map are being re-added to the error buffer so that errors with the + /// same primary span come out in a consistent order. + buffered_move_errors: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, Diag<'infcx>)>, + + buffered_mut_errors: FxIndexMap<Span, (Diag<'infcx>, usize)>, + + /// Buffer of diagnostics to be reported. A mixture of error and non-error diagnostics. + buffered_diags: Vec<BufferedDiag<'infcx>>, +} + +impl<'infcx, 'tcx> BorrowckDiags<'infcx, 'tcx> { + pub(crate) fn new() -> Self { + BorrowckDiags { + buffered_move_errors: BTreeMap::new(), + buffered_mut_errors: Default::default(), + buffered_diags: Default::default(), + } + } + + pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) { + self.buffered_diags.push(BufferedDiag::Error(diag)); + } + + pub(crate) fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) { + self.buffered_diags.push(BufferedDiag::NonError(diag)); + } +} + +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { + pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) { + self.diags.buffer_error(diag); + } + + pub(crate) fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) { + self.diags.buffer_non_error(diag); + } + + pub(crate) fn buffer_move_error( + &mut self, + move_out_indices: Vec<MoveOutIndex>, + place_and_err: (PlaceRef<'tcx>, Diag<'infcx>), + ) -> bool { + if let Some((_, diag)) = + self.diags.buffered_move_errors.insert(move_out_indices, place_and_err) + { + // Cancel the old diagnostic so we don't ICE + diag.cancel(); + false + } else { + true + } + } + + pub(crate) fn get_buffered_mut_error(&mut self, span: Span) -> Option<(Diag<'infcx>, usize)> { + // FIXME(#120456) - is `swap_remove` correct? + self.diags.buffered_mut_errors.swap_remove(&span) + } + + pub(crate) fn buffer_mut_error(&mut self, span: Span, diag: Diag<'infcx>, count: usize) { + self.diags.buffered_mut_errors.insert(span, (diag, count)); + } + + pub(crate) fn emit_errors(&mut self) -> Option<ErrorGuaranteed> { + let mut res = self.infcx.tainted_by_errors(); + + // Buffer any move errors that we collected and de-duplicated. + for (_, (_, diag)) in std::mem::take(&mut self.diags.buffered_move_errors) { + // We have already set tainted for this error, so just buffer it. + self.diags.buffer_error(diag); + } + for (_, (mut diag, count)) in std::mem::take(&mut self.diags.buffered_mut_errors) { + if count > 10 { + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] + diag.note(format!("...and {} other attempted mutable borrows", count - 10)); + } + self.diags.buffer_error(diag); + } + + if !self.diags.buffered_diags.is_empty() { + self.diags.buffered_diags.sort_by_key(|buffered_diag| buffered_diag.sort_span()); + for buffered_diag in self.diags.buffered_diags.drain(..) { + match buffered_diag { + BufferedDiag::Error(diag) => res = Some(diag.emit()), + BufferedDiag::NonError(diag) => diag.emit(), + } + } + } + + res + } + + pub(crate) fn has_buffered_diags(&self) -> bool { + self.diags.buffered_diags.is_empty() + } + + pub(crate) fn has_move_error( + &self, + move_out_indices: &[MoveOutIndex], + ) -> Option<&(PlaceRef<'tcx>, Diag<'infcx>)> { + self.diags.buffered_move_errors.get(move_out_indices) + } +} + impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure /// is moved after being invoked. diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index b59bdc26648..6571fb5ddac 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -16,14 +16,13 @@ // tidy-alphabetical-end use std::cell::RefCell; -use std::collections::BTreeMap; use std::marker::PhantomData; use std::ops::Deref; +use diagnostics::BorrowckDiags; use rustc_abi::FieldIdx; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::graph::dominators::Dominators; -use rustc_errors::Diag; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_index::bit_set::{BitSet, MixedBitSet}; @@ -41,7 +40,7 @@ use rustc_mir_dataflow::impls::{ EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces, }; use rustc_mir_dataflow::move_paths::{ - InitIndex, InitLocation, LookupResult, MoveData, MoveOutIndex, MovePathIndex, + InitIndex, InitLocation, LookupResult, MoveData, MovePathIndex, }; use rustc_mir_dataflow::{Analysis, EntryStates, Results, ResultsVisitor, visit_results}; use rustc_session::lint::builtin::UNUSED_MUT; @@ -217,7 +216,7 @@ fn do_mir_borrowck<'tcx>( // We also have a `#[rustc_regions]` annotation that causes us to dump // information. - let diags = &mut diags::BorrowckDiags::new(); + let diags = &mut BorrowckDiags::new(); nll::dump_annotation(&infcx, body, ®ioncx, &opt_closure_req, &opaque_type_values, diags); let movable_coroutine = @@ -566,7 +565,7 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { /// Results of Polonius analysis. polonius_output: Option<Box<PoloniusOutput>>, - diags: &'a mut diags::BorrowckDiags<'infcx, 'tcx>, + diags: &'a mut BorrowckDiags<'infcx, 'tcx>, move_errors: Vec<MoveError<'tcx>>, } @@ -2399,146 +2398,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { } } -mod diags { - use rustc_errors::ErrorGuaranteed; - - use super::*; - - enum BufferedDiag<'infcx> { - Error(Diag<'infcx>), - NonError(Diag<'infcx, ()>), - } - - impl<'infcx> BufferedDiag<'infcx> { - fn sort_span(&self) -> Span { - match self { - BufferedDiag::Error(diag) => diag.sort_span, - BufferedDiag::NonError(diag) => diag.sort_span, - } - } - } - - pub(crate) struct BorrowckDiags<'infcx, 'tcx> { - /// This field keeps track of move errors that are to be reported for given move indices. - /// - /// There are situations where many errors can be reported for a single move out (see - /// #53807) and we want only the best of those errors. - /// - /// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the - /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of - /// the `Place` of the previous most diagnostic. This happens instead of buffering the - /// error. Once all move errors have been reported, any diagnostics in this map are added - /// to the buffer to be emitted. - /// - /// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary - /// when errors in the map are being re-added to the error buffer so that errors with the - /// same primary span come out in a consistent order. - buffered_move_errors: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, Diag<'infcx>)>, - - buffered_mut_errors: FxIndexMap<Span, (Diag<'infcx>, usize)>, - - /// Buffer of diagnostics to be reported. A mixture of error and non-error diagnostics. - buffered_diags: Vec<BufferedDiag<'infcx>>, - } - - impl<'infcx, 'tcx> BorrowckDiags<'infcx, 'tcx> { - pub(crate) fn new() -> Self { - BorrowckDiags { - buffered_move_errors: BTreeMap::new(), - buffered_mut_errors: Default::default(), - buffered_diags: Default::default(), - } - } - - pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) { - self.buffered_diags.push(BufferedDiag::Error(diag)); - } - - pub(crate) fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) { - self.buffered_diags.push(BufferedDiag::NonError(diag)); - } - } - - impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { - pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) { - self.diags.buffer_error(diag); - } - - pub(crate) fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) { - self.diags.buffer_non_error(diag); - } - - pub(crate) fn buffer_move_error( - &mut self, - move_out_indices: Vec<MoveOutIndex>, - place_and_err: (PlaceRef<'tcx>, Diag<'infcx>), - ) -> bool { - if let Some((_, diag)) = - self.diags.buffered_move_errors.insert(move_out_indices, place_and_err) - { - // Cancel the old diagnostic so we don't ICE - diag.cancel(); - false - } else { - true - } - } - - pub(crate) fn get_buffered_mut_error( - &mut self, - span: Span, - ) -> Option<(Diag<'infcx>, usize)> { - // FIXME(#120456) - is `swap_remove` correct? - self.diags.buffered_mut_errors.swap_remove(&span) - } - - pub(crate) fn buffer_mut_error(&mut self, span: Span, diag: Diag<'infcx>, count: usize) { - self.diags.buffered_mut_errors.insert(span, (diag, count)); - } - - pub(crate) fn emit_errors(&mut self) -> Option<ErrorGuaranteed> { - let mut res = self.infcx.tainted_by_errors(); - - // Buffer any move errors that we collected and de-duplicated. - for (_, (_, diag)) in std::mem::take(&mut self.diags.buffered_move_errors) { - // We have already set tainted for this error, so just buffer it. - self.diags.buffer_error(diag); - } - for (_, (mut diag, count)) in std::mem::take(&mut self.diags.buffered_mut_errors) { - if count > 10 { - #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] - diag.note(format!("...and {} other attempted mutable borrows", count - 10)); - } - self.diags.buffer_error(diag); - } - - if !self.diags.buffered_diags.is_empty() { - self.diags.buffered_diags.sort_by_key(|buffered_diag| buffered_diag.sort_span()); - for buffered_diag in self.diags.buffered_diags.drain(..) { - match buffered_diag { - BufferedDiag::Error(diag) => res = Some(diag.emit()), - BufferedDiag::NonError(diag) => diag.emit(), - } - } - } - - res - } - - pub(crate) fn has_buffered_diags(&self) -> bool { - self.diags.buffered_diags.is_empty() - } - - pub(crate) fn has_move_error( - &self, - move_out_indices: &[MoveOutIndex], - ) -> Option<&(PlaceRef<'tcx>, Diag<'infcx>)> { - self.diags.buffered_move_errors.get(move_out_indices) - } - } -} - /// The degree of overlap between 2 places for borrow-checking. enum Overlap { /// The places might partially overlap - in this case, we give diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 49edb2813ec..6184f1484b5 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -26,7 +26,7 @@ use tracing::{debug, instrument}; use crate::borrow_set::BorrowSet; use crate::consumers::ConsumerOptions; -use crate::diagnostics::RegionErrors; +use crate::diagnostics::{BorrowckDiags, RegionErrors}; use crate::polonius::LocalizedOutlivesConstraintSet; use crate::polonius::legacy::{AllFacts, AllFactsExt, LocationTable, PoloniusOutput}; use crate::region_infer::RegionInferenceContext; @@ -298,7 +298,7 @@ pub(super) fn dump_annotation<'tcx, 'infcx>( regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>, opaque_type_values: &FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>, - diags: &mut crate::diags::BorrowckDiags<'infcx, 'tcx>, + diags: &mut BorrowckDiags<'infcx, 'tcx>, ) { let tcx = infcx.tcx; let base_def_id = tcx.typeck_root_def_id(body.source.def_id()); |
