diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index 74de766ba2317..7e8c48a155136 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -8,11 +8,12 @@ use rustc_middle::ty::TyCtxt; pub use super::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation}; pub use super::constraints::OutlivesConstraint; pub use super::dataflow::{BorrowIndex, Borrows, calculate_borrows_out_of_scope_at_location}; -pub use super::facts::{AllFacts as PoloniusInput, PoloniusRegionVid, RustcFacts}; -pub use super::location::{LocationTable, RichLocation}; -pub use super::nll::PoloniusOutput; pub use super::place_ext::PlaceExt; pub use super::places_conflict::{PlaceConflictBias, places_conflict}; +pub use super::polonius::legacy::{ + AllFacts as PoloniusInput, LocationTable, PoloniusOutput, PoloniusRegionVid, RichLocation, + RustcFacts, +}; pub use super::region_infer::RegionInferenceContext; /// Options determining the output behavior of [`get_body_with_borrowck_facts`]. diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 67be6ecdeb3d3..180046ca25620 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,126 @@ 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, + } + } +} + +#[derive(Default)] +pub(crate) struct BorrowckDiagnosticsBuffer<'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, (PlaceRef<'tcx>, Diag<'infcx>)>, + + buffered_mut_errors: FxIndexMap, usize)>, + + /// Buffer of diagnostics to be reported. A mixture of error and non-error diagnostics. + buffered_diags: Vec>, +} + +impl<'infcx, 'tcx> BorrowckDiagnosticsBuffer<'infcx, 'tcx> { + 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.buffered_diags.push(BufferedDiag::Error(diag)); + } + + pub(crate) fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) { + self.diags_buffer.buffer_non_error(diag); + } + + pub(crate) fn buffer_move_error( + &mut self, + move_out_indices: Vec, + place_and_err: (PlaceRef<'tcx>, Diag<'infcx>), + ) -> bool { + if let Some((_, diag)) = + self.diags_buffer.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_buffer.buffered_mut_errors.swap_remove(&span) + } + + pub(crate) fn buffer_mut_error(&mut self, span: Span, diag: Diag<'infcx>, count: usize) { + self.diags_buffer.buffered_mut_errors.insert(span, (diag, count)); + } + + pub(crate) fn emit_errors(&mut self) -> Option { + 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_buffer.buffered_move_errors) { + // We have already set tainted for this error, so just buffer it. + self.buffer_error(diag); + } + for (_, (mut diag, count)) in std::mem::take(&mut self.diags_buffer.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.buffer_error(diag); + } + + if !self.diags_buffer.buffered_diags.is_empty() { + self.diags_buffer.buffered_diags.sort_by_key(|buffered_diag| buffered_diag.sort_span()); + for buffered_diag in self.diags_buffer.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_buffer.buffered_diags.is_empty() + } + + pub(crate) fn has_move_error( + &self, + move_out_indices: &[MoveOutIndex], + ) -> Option<&(PlaceRef<'tcx>, Diag<'infcx>)> { + self.diags_buffer.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 8b968177c3c09..b061a450c83f7 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -16,14 +16,12 @@ // tidy-alphabetical-end use std::cell::RefCell; -use std::collections::BTreeMap; use std::marker::PhantomData; use std::ops::Deref; 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 +39,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; @@ -52,12 +50,13 @@ use tracing::{debug, instrument}; use crate::borrow_set::{BorrowData, BorrowSet}; use crate::consumers::{BodyWithBorrowckFacts, ConsumerOptions}; use crate::dataflow::{BorrowIndex, Borrowck, BorrowckDomain, Borrows}; -use crate::diagnostics::{AccessKind, IllegalMoveOriginKind, MoveError, RegionName}; -use crate::location::LocationTable; -use crate::nll::PoloniusOutput; +use crate::diagnostics::{ + AccessKind, BorrowckDiagnosticsBuffer, IllegalMoveOriginKind, MoveError, RegionName, +}; use crate::path_utils::*; use crate::place_ext::PlaceExt; use crate::places_conflict::{PlaceConflictBias, places_conflict}; +use crate::polonius::legacy::{LocationTable, PoloniusOutput}; use crate::prefixes::PrefixSet; use crate::region_infer::RegionInferenceContext; use crate::renumber::RegionCtxt; @@ -69,8 +68,6 @@ mod constraints; mod dataflow; mod def_use; mod diagnostics; -mod facts; -mod location; mod member_constraints; mod nll; mod path_utils; @@ -120,11 +117,10 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { return tcx.arena.alloc(result); } - let promoted: &IndexSlice<_, _> = &promoted.borrow(); - let opt_closure_req = do_mir_borrowck(tcx, input_body, promoted, None).0; + let borrowck_result = do_mir_borrowck(tcx, input_body, &*promoted.borrow(), None).0; debug!("mir_borrowck done"); - tcx.arena.alloc(opt_closure_req) + tcx.arena.alloc(borrowck_result) } /// Perform the actual borrow checking. @@ -215,14 +211,21 @@ fn do_mir_borrowck<'tcx>( consumer_options, ); - // Dump MIR results into a file, if that is enabled. This let us + // Dump MIR results into a file, if that is enabled. This lets us // write unit-tests, as well as helping with debugging. nll::dump_nll_mir(&infcx, body, ®ioncx, &opt_closure_req, &borrow_set); // We also have a `#[rustc_regions]` annotation that causes us to dump // information. - let diags = &mut diags::BorrowckDiags::new(); - nll::dump_annotation(&infcx, body, ®ioncx, &opt_closure_req, &opaque_type_values, diags); + let diags_buffer = &mut BorrowckDiagnosticsBuffer::default(); + nll::dump_annotation( + &infcx, + body, + ®ioncx, + &opt_closure_req, + &opaque_type_values, + diags_buffer, + ); let movable_coroutine = // The first argument is the coroutine type passed by value @@ -261,7 +264,7 @@ fn do_mir_borrowck<'tcx>( next_region_name: RefCell::new(1), polonius_output: None, move_errors: Vec::new(), - diags, + diags_buffer, }; MoveVisitor { ctxt: &mut promoted_mbcx }.visit_body(promoted_body); promoted_mbcx.report_move_errors(); @@ -300,7 +303,7 @@ fn do_mir_borrowck<'tcx>( next_region_name: RefCell::new(1), polonius_output, move_errors: Vec::new(), - diags, + diags_buffer, }; // Compute and report region errors, if any. @@ -570,7 +573,7 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { /// Results of Polonius analysis. polonius_output: Option>, - diags: &'a mut diags::BorrowckDiags<'infcx, 'tcx>, + diags_buffer: &'a mut BorrowckDiagnosticsBuffer<'infcx, 'tcx>, move_errors: Vec>, } @@ -2403,146 +2406,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, (PlaceRef<'tcx>, Diag<'infcx>)>, - - buffered_mut_errors: FxIndexMap, usize)>, - - /// Buffer of diagnostics to be reported. A mixture of error and non-error diagnostics. - buffered_diags: Vec>, - } - - 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, - 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 { - 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 4428e69584479..968b6d383c1b4 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -26,17 +26,14 @@ use tracing::{debug, instrument}; use crate::borrow_set::BorrowSet; use crate::consumers::ConsumerOptions; -use crate::diagnostics::RegionErrors; -use crate::facts::{AllFacts, AllFactsExt, RustcFacts}; -use crate::location::LocationTable; +use crate::diagnostics::{BorrowckDiagnosticsBuffer, RegionErrors}; use crate::polonius::LocalizedOutlivesConstraintSet; +use crate::polonius::legacy::{AllFacts, AllFactsExt, LocationTable, PoloniusOutput}; use crate::region_infer::RegionInferenceContext; use crate::type_check::{self, MirTypeckResults}; use crate::universal_regions::UniversalRegions; use crate::{BorrowckInferCtxt, polonius, renumber}; -pub type PoloniusOutput = Output; - /// The output of `nll::compute_regions`. This includes the computed `RegionInferenceContext`, any /// closure requirements to propagate, and any generated errors. pub(crate) struct NllOutput<'tcx> { @@ -121,7 +118,7 @@ pub(crate) fn compute_regions<'a, 'tcx>( // Create the region inference context, taking ownership of the // region inference data that was contained in `infcx`, and the // base constraints generated by the type-check. - let var_origins = infcx.get_region_var_origins(); + let var_infos = infcx.get_region_var_infos(); // If requested, emit legacy polonius facts. polonius::legacy::emit_facts( @@ -137,7 +134,7 @@ pub(crate) fn compute_regions<'a, 'tcx>( let mut regioncx = RegionInferenceContext::new( infcx, - var_origins, + var_infos, constraints, universal_region_relations, elements, @@ -301,7 +298,7 @@ pub(super) fn dump_annotation<'tcx, 'infcx>( regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, opaque_type_values: &FxIndexMap>, - diags: &mut crate::diags::BorrowckDiags<'infcx, 'tcx>, + diagnostics_buffer: &mut BorrowckDiagnosticsBuffer<'infcx, 'tcx>, ) { let tcx = infcx.tcx; let base_def_id = tcx.typeck_root_def_id(body.source.def_id()); @@ -347,7 +344,7 @@ pub(super) fn dump_annotation<'tcx, 'infcx>( err.note(format!("Inferred opaque type values:\n{opaque_type_values:#?}")); } - diags.buffer_non_error(err); + diagnostics_buffer.buffer_non_error(err); } fn for_each_region_constraint<'tcx>( diff --git a/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs index 9c4aa8ea1edb7..4a0c8d9b4b461 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs @@ -4,9 +4,8 @@ use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::move_paths::{LookupResult, MoveData}; use tracing::debug; +use super::{AllFacts, LocationIndex, LocationTable}; use crate::def_use::{self, DefUse}; -use crate::facts::AllFacts; -use crate::location::{LocationIndex, LocationTable}; use crate::universal_regions::UniversalRegions; /// Emit polonius facts for variable defs, uses, drops, and path accesses. diff --git a/compiler/rustc_borrowck/src/facts.rs b/compiler/rustc_borrowck/src/polonius/legacy/facts.rs similarity index 96% rename from compiler/rustc_borrowck/src/facts.rs rename to compiler/rustc_borrowck/src/polonius/legacy/facts.rs index ef8e757a54780..42c4e73321833 100644 --- a/compiler/rustc_borrowck/src/facts.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/facts.rs @@ -4,18 +4,20 @@ use std::fs::{self, File}; use std::io::Write; use std::path::Path; -use polonius_engine::{AllFacts as PoloniusFacts, Atom}; +use polonius_engine::{AllFacts as PoloniusFacts, Atom, Output}; use rustc_macros::extension; use rustc_middle::mir::Local; use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::move_paths::MovePathIndex; +use super::{LocationIndex, LocationTable}; use crate::BorrowIndex; -use crate::location::{LocationIndex, LocationTable}; #[derive(Copy, Clone, Debug)] pub struct RustcFacts; +pub type PoloniusOutput = Output; + rustc_index::newtype_index! { /// A (kinda) newtype of `RegionVid` so we can implement `Atom` on it. #[orderable] @@ -246,6 +248,6 @@ impl FactCell for RegionVid { impl FactCell for LocationIndex { fn to_string(&self, location_table: &LocationTable) -> String { - format!("{:?}", location_table.to_location(*self)) + format!("{:?}", location_table.to_rich_location(*self)) } } diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs index 178f70a673046..bb6d593d0d88e 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs @@ -9,9 +9,8 @@ use rustc_middle::mir::{ use rustc_middle::ty::TyCtxt; use tracing::debug; +use super::{AllFacts, LocationTable}; use crate::borrow_set::BorrowSet; -use crate::facts::AllFacts; -use crate::location::LocationTable; use crate::path_utils::*; use crate::{ AccessDepth, Activation, ArtificialField, BorrowIndex, Deep, LocalMutationIsAllowed, Read, diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs index fdde9fa047621..0148e0b286967 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs @@ -6,9 +6,8 @@ use rustc_middle::mir::{ use rustc_middle::ty::TyCtxt; use tracing::debug; +use super::{AllFacts, LocationTable}; use crate::borrow_set::BorrowSet; -use crate::facts::AllFacts; -use crate::location::LocationTable; use crate::places_conflict; /// Emit `loan_killed_at` and `cfg_edge` facts at the same time. diff --git a/compiler/rustc_borrowck/src/location.rs b/compiler/rustc_borrowck/src/polonius/legacy/location.rs similarity index 92% rename from compiler/rustc_borrowck/src/location.rs rename to compiler/rustc_borrowck/src/polonius/legacy/location.rs index fbe5f94ed42ca..4cb1202033cb9 100644 --- a/compiler/rustc_borrowck/src/location.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/location.rs @@ -65,7 +65,7 @@ impl LocationTable { LocationIndex::from_usize(start_index + statement_index * 2 + 1) } - pub fn to_location(&self, index: LocationIndex) -> RichLocation { + pub fn to_rich_location(&self, index: LocationIndex) -> RichLocation { let point_index = index.index(); // Find the basic block. We have a vector with the @@ -97,6 +97,13 @@ impl LocationTable { RichLocation::Mid(Location { block, statement_index }) } } + + pub fn to_location(&self, index: LocationIndex) -> Location { + match self.to_rich_location(index) { + RichLocation::Start(location) => location, + RichLocation::Mid(location) => location, + } + } } impl LocationIndex { diff --git a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs index 60fd2afe63e1c..45bdbd1e9997e 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs @@ -13,8 +13,6 @@ use tracing::debug; use crate::borrow_set::BorrowSet; use crate::constraints::OutlivesConstraint; -use crate::facts::{AllFacts, PoloniusRegionVid}; -use crate::location::LocationTable; use crate::type_check::MirTypeckRegionConstraints; use crate::type_check::free_region_relations::UniversalRegionRelations; use crate::universal_regions::UniversalRegions; @@ -22,6 +20,10 @@ use crate::universal_regions::UniversalRegions; mod accesses; mod loan_invalidations; mod loan_kills; +mod location; +pub use self::location::*; +mod facts; +pub use self::facts::*; /// When requested, emit most of the facts needed by polonius: /// - moves and assignments diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index a71508c84f68c..2150759d329ea 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -30,7 +30,7 @@ use crate::constraints::{ConstraintSccIndex, OutlivesConstraint, OutlivesConstra use crate::dataflow::BorrowIndex; use crate::diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo}; use crate::member_constraints::{MemberConstraintSet, NllMemberConstraintIndex}; -use crate::nll::PoloniusOutput; +use crate::polonius::legacy::PoloniusOutput; use crate::region_infer::reverse_sccs::ReverseSccGraph; use crate::region_infer::values::{LivenessValues, RegionElement, RegionValues, ToElementIndex}; use crate::type_check::free_region_relations::UniversalRegionRelations; diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 2c658edc41cce..c7a2d32b31dc8 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -15,7 +15,6 @@ use rustc_span::DUMMY_SP; use rustc_trait_selection::traits::query::type_op::{DropckOutlives, TypeOp, TypeOpOutput}; use tracing::debug; -use crate::location::RichLocation; use crate::polonius; use crate::region_infer::values::{self, LiveLoans}; use crate::type_check::liveness::local_use_map::LocalUseMap; @@ -211,7 +210,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { /// /// Add facts for all locals with free regions, since regions may outlive /// the function body only at certain nodes in the CFG. - fn add_extra_drop_facts(&mut self, relevant_live_locals: &[Local]) -> Option<()> { + fn add_extra_drop_facts(&mut self, relevant_live_locals: &[Local]) { // This collect is more necessary than immediately apparent // because these facts go into `add_drop_live_facts_for()`, // which also writes to `all_facts`, and so this is genuinely @@ -221,41 +220,30 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { // and probably maybe plausibly does not need to go back in. // It may be necessary to just pick out the parts of // `add_drop_live_facts_for()` that make sense. + let Some(facts) = self.cx.typeck.all_facts.as_ref() else { return }; let facts_to_add: Vec<_> = { - let drop_used = &self.cx.typeck.all_facts.as_ref()?.var_dropped_at; - let relevant_live_locals: FxIndexSet<_> = relevant_live_locals.iter().copied().collect(); - drop_used + facts + .var_dropped_at .iter() - .filter_map(|(local, location_index)| { - let local_ty = self.cx.body.local_decls[*local].ty; - if relevant_live_locals.contains(local) || !local_ty.has_free_regions() { + .filter_map(|&(local, location_index)| { + let local_ty = self.cx.body.local_decls[local].ty; + if relevant_live_locals.contains(&local) || !local_ty.has_free_regions() { return None; } - let location = match self.cx.typeck.location_table.to_location(*location_index) - { - RichLocation::Start(l) => l, - RichLocation::Mid(l) => l, - }; - - Some((*local, local_ty, location)) + let location = self.cx.typeck.location_table.to_location(location_index); + Some((local, local_ty, location)) }) .collect() }; - // FIXME: these locations seem to have a special meaning (e.g. everywhere, at the end, - // ...), but I don't know which one. Please help me rename it to something descriptive! - // Also, if this IntervalSet is used in many places, it maybe should have a newtype'd - // name with a description of what it means for future mortals passing by. - let locations = IntervalSet::new(self.cx.elements.num_points()); - + let live_at = IntervalSet::new(self.cx.elements.num_points()); for (local, local_ty, location) in facts_to_add { - self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations); + self.cx.add_drop_live_facts_for(local, local_ty, &[location], &live_at); } - Some(()) } /// Clear the value of fields that are "per local variable". diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 3968900d0471d..10fb8a399a267 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -47,10 +47,9 @@ use tracing::{debug, instrument, trace}; use crate::borrow_set::BorrowSet; use crate::constraints::{OutlivesConstraint, OutlivesConstraintSet}; use crate::diagnostics::UniverseInfo; -use crate::facts::AllFacts; -use crate::location::LocationTable; use crate::member_constraints::MemberConstraintSet; use crate::polonius::PoloniusContext; +use crate::polonius::legacy::{AllFacts, LocationTable}; use crate::region_infer::TypeTest; use crate::region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderIndices}; use crate::renumber::RegionCtxt; diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index c5a56005c0639..1f7180fb80a0c 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -945,7 +945,7 @@ impl<'tcx> InferCtxt<'tcx> { /// Clone the list of variable regions. This is used only during NLL processing /// to put the set of region variables into the NLL region context. - pub fn get_region_var_origins(&self) -> VarInfos { + pub fn get_region_var_infos(&self) -> VarInfos { let inner = self.inner.borrow(); assert!(!UndoLogs::>::in_snapshot(&inner.undo_log)); let storage = inner.region_constraint_storage.as_ref().expect("regions already resolved");