Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions compiler/rustc_borrowck/src/consumers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub use super::polonius::legacy::{
};
pub use super::region_infer::RegionInferenceContext;
use crate::BorrowCheckRootCtxt;
use crate::region_infer::InferredRegions;

/// Struct used during mir borrowck to collect bodies with facts for a typeck root and all
/// its nested bodies.
Expand Down Expand Up @@ -89,9 +90,10 @@ pub struct BodyWithBorrowckFacts<'tcx> {
pub promoted: IndexVec<Promoted, Body<'tcx>>,
/// The set of borrows occurring in `body` with data about them.
pub borrow_set: BorrowSet<'tcx>,
/// Context generated during borrowck, intended to be passed to
/// The inferred region values. These are included because they
/// are necessary as input to
/// [`calculate_borrows_out_of_scope_at_location`].
pub region_inference_context: RegionInferenceContext<'tcx>,
pub inferred_regions: InferredRegions<'tcx>,
/// The table that maps Polonius points to locations in the table.
/// Populated when using [`ConsumerOptions::PoloniusInputFacts`]
/// or [`ConsumerOptions::PoloniusOutputFacts`].
Expand Down
43 changes: 21 additions & 22 deletions compiler/rustc_borrowck/src/dataflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ use rustc_mir_dataflow::impls::{
use rustc_mir_dataflow::{Analysis, GenKill, JoinSemiLattice};
use tracing::debug;

use crate::{BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, places_conflict};
use crate::region_infer::InferredRegions;
use crate::region_infer::values::LivenessValues;
use crate::{BorrowSet, PlaceConflictBias, PlaceExt, places_conflict};

// This analysis is different to most others. Its results aren't computed with
// `iterate_to_fixpoint`, but are instead composed from the results of three sub-analyses that are
Expand Down Expand Up @@ -182,34 +184,33 @@ struct OutOfScopePrecomputer<'a, 'tcx> {
visited: DenseBitSet<mir::BasicBlock>,
visit_stack: Vec<mir::BasicBlock>,
body: &'a Body<'tcx>,
regioncx: &'a RegionInferenceContext<'tcx>,
borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
}

impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
fn compute(
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
scc_values: &InferredRegions<'tcx>,
borrow_set: &BorrowSet<'tcx>,
) -> FxIndexMap<Location, Vec<BorrowIndex>> {
let mut prec = OutOfScopePrecomputer {
visited: DenseBitSet::new_empty(body.basic_blocks.len()),
visit_stack: vec![],
body,
regioncx,
borrows_out_of_scope_at_location: FxIndexMap::default(),
};
for (borrow_index, borrow_data) in borrow_set.iter_enumerated() {
let borrow_region = borrow_data.region;
let location = borrow_data.reserve_location;
prec.precompute_borrows_out_of_scope(borrow_index, borrow_region, location);
prec.precompute_borrows_out_of_scope(scc_values, borrow_index, borrow_region, location);
}

prec.borrows_out_of_scope_at_location
}

fn precompute_borrows_out_of_scope(
&mut self,
scc_values: &InferredRegions<'tcx>,
borrow_index: BorrowIndex,
borrow_region: RegionVid,
first_location: Location,
Expand All @@ -222,12 +223,9 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
let first_lo = first_location.statement_index;
let first_hi = first_bb_data.statements.len();

if let Some(kill_stmt) = self.regioncx.first_non_contained_inclusive(
borrow_region,
first_block,
first_lo,
first_hi,
) {
if let Some(kill_stmt) =
scc_values.first_non_contained_inclusive(borrow_region, first_block, first_lo, first_hi)
{
let kill_location = Location { block: first_block, statement_index: kill_stmt };
// If region does not contain a point at the location, then add to list and skip
// successor locations.
Expand Down Expand Up @@ -255,7 +253,7 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
let bb_data = &self.body[block];
let num_stmts = bb_data.statements.len();
if let Some(kill_stmt) =
self.regioncx.first_non_contained_inclusive(borrow_region, block, 0, num_stmts)
scc_values.first_non_contained_inclusive(borrow_region, block, 0, num_stmts)
{
let kill_location = Location { block, statement_index: kill_stmt };
// If region does not contain a point at the location, then add to list and skip
Expand Down Expand Up @@ -285,25 +283,24 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
// This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`.
pub fn calculate_borrows_out_of_scope_at_location<'tcx>(
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
scc_values: &InferredRegions<'tcx>,
borrow_set: &BorrowSet<'tcx>,
) -> FxIndexMap<Location, Vec<BorrowIndex>> {
OutOfScopePrecomputer::compute(body, regioncx, borrow_set)
OutOfScopePrecomputer::compute(body, scc_values, borrow_set)
}

struct PoloniusOutOfScopePrecomputer<'a, 'tcx> {
visited: DenseBitSet<mir::BasicBlock>,
visit_stack: Vec<mir::BasicBlock>,
body: &'a Body<'tcx>,
regioncx: &'a RegionInferenceContext<'tcx>,

liveness_values: &'a LivenessValues,
loans_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
}

impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
fn compute(
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
liveness_values: &LivenessValues,
borrow_set: &BorrowSet<'tcx>,
) -> FxIndexMap<Location, Vec<BorrowIndex>> {
// The in-tree polonius analysis computes loans going out of scope using the
Expand All @@ -312,7 +309,7 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
visited: DenseBitSet::new_empty(body.basic_blocks.len()),
visit_stack: vec![],
body,
regioncx,
liveness_values,
loans_out_of_scope_at_location: FxIndexMap::default(),
};
for (loan_idx, loan_data) in borrow_set.iter_enumerated() {
Expand Down Expand Up @@ -412,7 +409,8 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
// Reachability is location-insensitive, and we could take advantage of that, by jumping
// to a further point than just the next statement: we can jump to the furthest point
// within the block where `r` is live.
if self.regioncx.is_loan_live_at(loan_idx, location) {
let point = self.liveness_values.point_from_location(location);
if self.liveness_values.is_loan_live_at(loan_idx, point) {
continue;
}

Expand All @@ -429,14 +427,15 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
pub fn new(
tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
liveness_values: &'a LivenessValues,
scc_values: &InferredRegions<'tcx>,
borrow_set: &'a BorrowSet<'tcx>,
) -> Self {
let borrows_out_of_scope_at_location =
if !tcx.sess.opts.unstable_opts.polonius.is_next_enabled() {
calculate_borrows_out_of_scope_at_location(body, regioncx, borrow_set)
calculate_borrows_out_of_scope_at_location(body, scc_values, borrow_set)
} else {
PoloniusOutOfScopePrecomputer::compute(body, regioncx, borrow_set)
PoloniusOutOfScopePrecomputer::compute(body, liveness_values, borrow_set)
};
Borrows { tcx, body, borrow_set, borrows_out_of_scope_at_location }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -403,8 +403,8 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
// started MIR borrowchecking with, so the region
// constraints have already been taken. Use the data from
// our `mbcx` instead.
|vid| RegionVariableOrigin::Nll(mbcx.regioncx.definitions[vid].origin),
|vid| mbcx.regioncx.definitions[vid].universe,
|vid| RegionVariableOrigin::Nll(mbcx.definitions[vid].origin),
|vid| mbcx.definitions[vid].universe,
)
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3434,7 +3434,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {

let tcx = self.infcx.tcx;

let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
let return_ty = self.universal_regions().unnormalized_output_ty;

// to avoid panics
if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator)
Expand Down
34 changes: 24 additions & 10 deletions compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use super::{RegionName, UseSpans, find_use};
use crate::borrow_set::BorrowData;
use crate::constraints::OutlivesConstraint;
use crate::nll::ConstraintDescription;
use crate::region_infer::{BlameConstraint, Cause};
use crate::region_infer::{BlameConstraint, Cause, ConstraintSearch};
use crate::{MirBorrowckCtxt, WriteKind};

#[derive(Debug)]
Expand Down Expand Up @@ -572,14 +572,23 @@ fn suggest_rewrite_if_let<G: EmissionGuarantee>(
}
}

impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
pub(crate) fn constraint_search<'mbc>(&'mbc self) -> ConstraintSearch<'mbc, 'tcx> {
ConstraintSearch {
definitions: self.definitions,
fr_static: self.universal_regions().fr_static,
constraint_graph: &self.constraint_graph,
constraints: &self.outlives_constraints,
}
}

fn free_region_constraint_info(
&self,
borrow_region: RegionVid,
outlived_region: RegionVid,
) -> (ConstraintCategory<'tcx>, bool, Span, Option<RegionName>, Vec<OutlivesConstraint<'tcx>>)
{
let (blame_constraint, path) = self.regioncx.best_blame_constraint(
let (blame_constraint, path) = self.constraint_search().best_blame_constraint(
borrow_region,
NllRegionVariableOrigin::FreeRegion,
outlived_region,
Expand Down Expand Up @@ -611,14 +620,17 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
borrow: &BorrowData<'tcx>,
kind_place: Option<(WriteKind, Place<'tcx>)>,
) -> BorrowExplanation<'tcx> {
let regioncx = &self.regioncx;
let body: &Body<'_> = self.body;
let tcx = self.infcx.tcx;

let borrow_region_vid = borrow.region;
debug!(?borrow_region_vid);

let mut region_sub = self.regioncx.find_sub_region_live_at(borrow_region_vid, location);
let mut region_sub = self.constraint_search().find_sub_region_live_at(
&self.liveness_constraints,
borrow_region_vid,
location,
);
debug!(?region_sub);

let mut use_location = location;
Expand All @@ -630,11 +642,13 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
// loop iteration. In this case, try using the loop terminator location in
// `find_sub_region_live_at`.
if let Some(loop_terminator_location) =
regioncx.find_loop_terminator_location(borrow.region, body)
self.scc_values.find_loop_terminator_location(borrow.region, body)
{
region_sub = self
.regioncx
.find_sub_region_live_at(borrow_region_vid, loop_terminator_location);
region_sub = self.constraint_search().find_sub_region_live_at(
&self.liveness_constraints,
borrow_region_vid,
loop_terminator_location,
);
debug!("explain_why_borrow_contains_point: region_sub in loop={:?}", region_sub);
use_location = loop_terminator_location;
use_in_later_iteration_of_loop = true;
Expand All @@ -658,7 +672,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
false
}
};
match find_use::find(body, regioncx, tcx, region_sub, use_location) {
match find_use::find(body, self.scc_values, tcx, region_sub, use_location) {
Some(Cause::LiveVar(local, location)) if !is_local_boring(local) => {
let span = body.source_info(location).span;
let spans = self
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_borrowck/src/diagnostics/find_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@ use rustc_middle::mir::{self, Body, Local, Location};
use rustc_middle::ty::{RegionVid, TyCtxt};

use crate::def_use::{self, DefUse};
use crate::region_infer::{Cause, RegionInferenceContext};
use crate::region_infer::{Cause, InferredRegions};

pub(crate) fn find<'tcx>(
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
scc_values: &InferredRegions<'tcx>,
tcx: TyCtxt<'tcx>,
region_vid: RegionVid,
start_point: Location,
) -> Option<Cause> {
let mut uf = UseFinder { body, regioncx, tcx, region_vid, start_point };
let mut uf = UseFinder { body, tcx, region_vid, start_point, scc_values: &scc_values };

uf.find()
}

struct UseFinder<'a, 'tcx> {
body: &'a Body<'tcx>,
regioncx: &'a RegionInferenceContext<'tcx>,
scc_values: &'a InferredRegions<'tcx>,
tcx: TyCtxt<'tcx>,
region_vid: RegionVid,
start_point: Location,
Expand All @@ -35,7 +35,7 @@ impl<'a, 'tcx> UseFinder<'a, 'tcx> {

queue.push_back(self.start_point);
while let Some(p) = queue.pop_front() {
if !self.regioncx.region_contains(self.region_vid, p) {
if !self.scc_values.region_contains(self.region_vid, p) {
continue;
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let tcx = self.infcx.tcx;
let Some((gat_hir_id, generics)) = path.iter().find_map(|constraint| {
let outlived = constraint.sub;
if let Some(origin) = self.regioncx.definitions.get(outlived)
if let Some(origin) = self.definitions.get(outlived)
&& let NllRegionVariableOrigin::Placeholder(placeholder) = origin.origin
&& let Some(id) = placeholder.bound.kind.get_id()
&& let Some(placeholder_id) = id.as_local()
Expand Down
22 changes: 12 additions & 10 deletions compiler/rustc_borrowck/src/diagnostics/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ use rustc_trait_selection::errors::impl_trait_overcapture_suggestion;

use crate::MirBorrowckCtxt;
use crate::borrow_set::BorrowData;
use crate::consumers::RegionInferenceContext;
use crate::region_infer::ConstraintSearch;
use crate::region_infer::opaque_types::DeferredOpaqueTypeError;
use crate::type_check::Locations;
use crate::universal_regions::UniversalRegions;

impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
pub(crate) fn report_opaque_type_errors(&mut self, errors: Vec<DeferredOpaqueTypeError<'tcx>>) {
Expand All @@ -42,12 +43,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
member_region,
} => {
let named_ty =
self.regioncx.name_regions_for_member_constraint(infcx.tcx, hidden_type.ty);
let named_key = self
.regioncx
.name_regions_for_member_constraint(infcx.tcx, opaque_type_key);
self.name_regions_for_member_constraint(infcx.tcx, hidden_type.ty);
let named_key =
self.name_regions_for_member_constraint(infcx.tcx, opaque_type_key);
let named_region =
self.regioncx.name_regions_for_member_constraint(infcx.tcx, member_region);
self.name_regions_for_member_constraint(infcx.tcx, member_region);
let diag = unexpected_hidden_region_diagnostic(
infcx,
self.mir_def_id(),
Expand Down Expand Up @@ -107,9 +107,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let tcx = self.infcx.tcx;
let ControlFlow::Break((opaque_def_id, offending_region_idx, location)) = ty
.visit_with(&mut FindOpaqueRegion {
regioncx: &self.regioncx,
tcx,
borrow_region: borrow.region,
universal_regions: self.universal_regions(),
constraint_search: self.constraint_search(),
})
else {
continue;
Expand Down Expand Up @@ -209,8 +210,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
/// This visitor contains the bulk of the logic for this lint.
struct FindOpaqueRegion<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
regioncx: &'a RegionInferenceContext<'tcx>,
constraint_search: ConstraintSearch<'a, 'tcx>,
borrow_region: ty::RegionVid,
universal_regions: &'a UniversalRegions<'tcx>,
}

impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindOpaqueRegion<'_, 'tcx> {
Expand All @@ -237,11 +239,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindOpaqueRegion<'_, 'tcx> {
if opaque_region.is_bound() {
continue;
}
let opaque_region_vid = self.regioncx.to_region_vid(opaque_region);
let opaque_region_vid = self.universal_regions.to_region_vid(opaque_region);

// Find a path between the borrow region and our opaque capture.
if let Some(path) = self
.regioncx
.constraint_search
.constraint_path_between_regions(self.borrow_region, opaque_region_vid)
{
for constraint in path {
Expand Down
Loading
Loading