summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_borrowck/src/nll.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_borrowck/src/nll.rs')
-rw-r--r--compiler/rustc_borrowck/src/nll.rs207
1 files changed, 40 insertions, 167 deletions
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 0ea4401a8..6781c6a75 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -2,16 +2,17 @@
#![deny(rustc::diagnostic_outside_of_impl)]
//! The entry point of the NLL borrow checker.
+use polonius_engine::{Algorithm, Output};
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir::def_id::LocalDefId;
use rustc_index::IndexSlice;
use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere};
-use rustc_middle::mir::{
- Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted,
- START_BLOCK,
-};
+use rustc_middle::mir::{Body, ClosureOutlivesSubject, ClosureRegionRequirements, Promoted};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt};
+use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
+use rustc_mir_dataflow::move_paths::MoveData;
+use rustc_mir_dataflow::ResultsCursor;
use rustc_span::symbol::sym;
use std::env;
use std::io;
@@ -19,25 +20,18 @@ use std::path::PathBuf;
use std::rc::Rc;
use std::str::FromStr;
-use polonius_engine::{Algorithm, Output};
-
-use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
-use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData};
-use rustc_mir_dataflow::ResultsCursor;
-
use crate::{
borrow_set::BorrowSet,
- constraint_generation,
consumers::ConsumerOptions,
diagnostics::RegionErrors,
facts::{AllFacts, AllFactsExt, RustcFacts},
- invalidation,
location::LocationTable,
+ polonius,
region_infer::{values::RegionValueElements, RegionInferenceContext},
renumber,
type_check::{self, MirTypeckRegionConstraints, MirTypeckResults},
universal_regions::UniversalRegions,
- BorrowckInferCtxt, Upvar,
+ BorrowckInferCtxt,
};
pub type PoloniusOutput = Output<RustcFacts>;
@@ -78,81 +72,6 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
universal_regions
}
-// This function populates an AllFacts instance with base facts related to
-// MovePaths and needed for the move analysis.
-fn populate_polonius_move_facts(
- all_facts: &mut AllFacts,
- move_data: &MoveData<'_>,
- location_table: &LocationTable,
- body: &Body<'_>,
-) {
- all_facts
- .path_is_var
- .extend(move_data.rev_lookup.iter_locals_enumerated().map(|(l, r)| (r, l)));
-
- for (child, move_path) in move_data.move_paths.iter_enumerated() {
- if let Some(parent) = move_path.parent {
- all_facts.child_path.push((child, parent));
- }
- }
-
- let fn_entry_start =
- location_table.start_index(Location { block: START_BLOCK, statement_index: 0 });
-
- // initialized_at
- for init in move_data.inits.iter() {
- match init.location {
- InitLocation::Statement(location) => {
- let block_data = &body[location.block];
- let is_terminator = location.statement_index == block_data.statements.len();
-
- if is_terminator && init.kind == InitKind::NonPanicPathOnly {
- // We are at the terminator of an init that has a panic path,
- // and where the init should not happen on panic
-
- for successor in block_data.terminator().successors() {
- if body[successor].is_cleanup {
- continue;
- }
-
- // The initialization happened in (or rather, when arriving at)
- // the successors, but not in the unwind block.
- let first_statement = Location { block: successor, statement_index: 0 };
- all_facts
- .path_assigned_at_base
- .push((init.path, location_table.start_index(first_statement)));
- }
- } else {
- // In all other cases, the initialization just happens at the
- // midpoint, like any other effect.
- all_facts
- .path_assigned_at_base
- .push((init.path, location_table.mid_index(location)));
- }
- }
- // Arguments are initialized on function entry
- InitLocation::Argument(local) => {
- assert!(body.local_kind(local) == LocalKind::Arg);
- all_facts.path_assigned_at_base.push((init.path, fn_entry_start));
- }
- }
- }
-
- for (local, path) in move_data.rev_lookup.iter_locals_enumerated() {
- if body.local_kind(local) != LocalKind::Arg {
- // Non-arguments start out deinitialised; we simulate this with an
- // initial move:
- all_facts.path_moved_at_base.push((path, fn_entry_start));
- }
- }
-
- // moved_out_at
- // deinitialisation is assumed to always happen!
- all_facts
- .path_moved_at_base
- .extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source))));
-}
-
/// Computes the (non-lexical) regions from the input MIR.
///
/// This may result in errors being reported.
@@ -166,7 +85,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'cx, 'tcx>>,
move_data: &MoveData<'tcx>,
borrow_set: &BorrowSet<'tcx>,
- upvars: &[Upvar<'tcx>],
+ upvars: &[&ty::CapturedPlace<'tcx>],
consumer_options: Option<ConsumerOptions>,
) -> NllOutput<'tcx> {
let is_polonius_legacy_enabled = infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled();
@@ -179,70 +98,26 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
let universal_regions = Rc::new(universal_regions);
- let elements = &Rc::new(RegionValueElements::new(&body));
+ let elements = &Rc::new(RegionValueElements::new(body));
// Run the MIR type-checker.
- let MirTypeckResults {
- constraints,
- universal_region_relations,
- opaque_type_values,
- live_loans,
- } = type_check::type_check(
- infcx,
- param_env,
- body,
- promoted,
- &universal_regions,
- location_table,
- borrow_set,
- &mut all_facts,
- flow_inits,
- move_data,
- elements,
- upvars,
- polonius_input,
- );
-
- if let Some(all_facts) = &mut all_facts {
- let _prof_timer = infcx.tcx.prof.generic_activity("polonius_fact_generation");
- all_facts.universal_region.extend(universal_regions.universal_regions());
- populate_polonius_move_facts(all_facts, move_data, location_table, &body);
-
- // Emit universal regions facts, and their relations, for Polonius.
- //
- // 1: universal regions are modeled in Polonius as a pair:
- // - the universal region vid itself.
- // - a "placeholder loan" associated to this universal region. Since they don't exist in
- // the `borrow_set`, their `BorrowIndex` are synthesized as the universal region index
- // added to the existing number of loans, as if they succeeded them in the set.
- //
- let borrow_count = borrow_set.len();
- debug!(
- "compute_regions: polonius placeholders, num_universals={}, borrow_count={}",
- universal_regions.len(),
- borrow_count
+ let MirTypeckResults { constraints, universal_region_relations, opaque_type_values } =
+ type_check::type_check(
+ infcx,
+ param_env,
+ body,
+ promoted,
+ &universal_regions,
+ location_table,
+ borrow_set,
+ &mut all_facts,
+ flow_inits,
+ move_data,
+ elements,
+ upvars,
+ polonius_input,
);
- for universal_region in universal_regions.universal_regions() {
- let universal_region_idx = universal_region.index();
- let placeholder_loan_idx = borrow_count + universal_region_idx;
- all_facts.placeholder.push((universal_region, placeholder_loan_idx.into()));
- }
-
- // 2: the universal region relations `outlives` constraints are emitted as
- // `known_placeholder_subset` facts.
- for (fr1, fr2) in universal_region_relations.known_outlives() {
- if fr1 != fr2 {
- debug!(
- "compute_regions: emitting polonius `known_placeholder_subset` \
- fr1={:?}, fr2={:?}",
- fr1, fr2
- );
- all_facts.known_placeholder_subset.push((fr1, fr2));
- }
- }
- }
-
// 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.
@@ -250,7 +125,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
let MirTypeckRegionConstraints {
placeholder_indices,
placeholder_index_to_region: _,
- mut liveness_constraints,
+ liveness_constraints,
outlives_constraints,
member_constraints,
universe_causes,
@@ -258,13 +133,16 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
} = constraints;
let placeholder_indices = Rc::new(placeholder_indices);
- constraint_generation::generate_constraints(
- infcx,
- &mut liveness_constraints,
+ // If requested, emit legacy polonius facts.
+ polonius::emit_facts(
&mut all_facts,
+ infcx.tcx,
location_table,
- &body,
+ body,
borrow_set,
+ move_data,
+ &universal_regions,
+ &universal_region_relations,
);
let mut regioncx = RegionInferenceContext::new(
@@ -279,17 +157,12 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
type_tests,
liveness_constraints,
elements,
- live_loans,
);
- // Generate various additional constraints.
- invalidation::generate_invalidates(infcx.tcx, &mut all_facts, location_table, body, borrow_set);
-
- let def_id = body.source.def_id();
-
- // Dump facts if requested.
+ // If requested: dump NLL facts, and run legacy polonius analysis.
let polonius_output = all_facts.as_ref().and_then(|all_facts| {
if infcx.tcx.sess.opts.unstable_opts.nll_facts {
+ let def_id = body.source.def_id();
let def_path = infcx.tcx.def_path(def_id);
let dir_path = PathBuf::from(&infcx.tcx.sess.opts.unstable_opts.nll_facts_dir)
.join(def_path.to_filename_friendly_no_crate());
@@ -302,7 +175,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
let algorithm = Algorithm::from_str(&algorithm).unwrap();
debug!("compute_regions: using polonius algorithm {:?}", algorithm);
let _prof_timer = infcx.tcx.prof.generic_activity("polonius_analysis");
- Some(Rc::new(Output::compute(&all_facts, algorithm, false)))
+ Some(Rc::new(Output::compute(all_facts, algorithm, false)))
} else {
None
}
@@ -310,17 +183,17 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
// Solve the region constraints.
let (closure_region_requirements, nll_errors) =
- regioncx.solve(infcx, param_env, &body, polonius_output.clone());
+ regioncx.solve(infcx, param_env, body, polonius_output.clone());
if !nll_errors.is_empty() {
// Suppress unhelpful extra errors in `infer_opaque_types`.
- infcx.set_tainted_by_errors(infcx.tcx.sess.delay_span_bug(
+ infcx.set_tainted_by_errors(infcx.tcx.sess.span_delayed_bug(
body.span,
"`compute_regions` tainted `infcx` with errors but did not emit any errors",
));
}
- let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, opaque_type_values);
+ let remapped_opaque_tys = regioncx.infer_opaque_types(infcx, opaque_type_values);
NllOutput {
regioncx,
@@ -407,7 +280,7 @@ pub(super) fn dump_annotation<'tcx>(
let def_span = tcx.def_span(body.source.def_id());
let mut err = if let Some(closure_region_requirements) = closure_region_requirements {
- let mut err = tcx.sess.diagnostic().span_note_diag(def_span, "external requirements");
+ let mut err = tcx.sess.dcx().struct_span_note(def_span, "external requirements");
regioncx.annotate(tcx, &mut err);
@@ -426,7 +299,7 @@ pub(super) fn dump_annotation<'tcx>(
err
} else {
- let mut err = tcx.sess.diagnostic().span_note_diag(def_span, "no external requirements");
+ let mut err = tcx.sess.dcx().struct_span_note(def_span, "no external requirements");
regioncx.annotate(tcx, &mut err);
err