Auto merge of #134914 - lqd:polonius-next-episode-5, r=jackh726
A couple datalog/borrowck cleanups As discussed on zulip, here's a chill one in between slightly more interesting PRs: - I hadn't noticed there still were a couple of datalog-related modules outside of their dedicated `polonius` module (go to horn-clause jail, bonk!). - there somehow was both a `diags` module and a `diagnostics` module. - a couple other tiny things being renamed -- let me know what you think. As requested I've tried to have somewhat granular commits to ease review, but the last two or three could be squashed together, since they're all related to the `diags` module (but moving its contents is less tedious to check in its own commit). r? `@jackh726`
This commit is contained in:
commit
2061630860
14 changed files with 189 additions and 210 deletions
|
@ -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`].
|
||||
|
|
|
@ -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<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> 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<MoveOutIndex>,
|
||||
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<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_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.
|
||||
|
|
|
@ -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<Box<PoloniusOutput>>,
|
||||
|
||||
diags: &'a mut diags::BorrowckDiags<'infcx, 'tcx>,
|
||||
diags_buffer: &'a mut BorrowckDiagnosticsBuffer<'infcx, 'tcx>,
|
||||
move_errors: Vec<MoveError<'tcx>>,
|
||||
}
|
||||
|
||||
|
@ -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<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
|
||||
|
|
|
@ -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<RustcFacts>;
|
||||
|
||||
/// 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<ClosureRegionRequirements<'tcx>>,
|
||||
opaque_type_values: &FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
|
||||
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>(
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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<RustcFacts>;
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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".
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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::<UndoLog<'_>>::in_snapshot(&inner.undo_log));
|
||||
let storage = inner.region_constraint_storage.as_ref().expect("regions already resolved");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue