Skip to content

[experimental, do not merge!] a faster implementation of Polonius #141326

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
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
3 changes: 3 additions & 0 deletions compiler/rustc_borrowck/src/borrow_set.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::cell::OnceCell;
use std::fmt;
use std::ops::Index;

@@ -84,6 +85,7 @@ pub struct BorrowData<'tcx> {
pub(crate) borrowed_place: mir::Place<'tcx>,
/// Place to which the borrow was stored
pub(crate) assigned_place: mir::Place<'tcx>,
pub(crate) dependent_regions: OnceCell<DenseBitSet<RegionVid>>,
}

// These methods are public to support borrowck consumers.
@@ -261,6 +263,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
activation_location: TwoPhaseActivation::NotTwoPhase,
borrowed_place,
assigned_place: *assigned_place,
dependent_regions: OnceCell::new(),
};
let (idx, _) = self.location_map.insert_full(location, borrow);
let idx = BorrowIndex::from(idx);
30 changes: 29 additions & 1 deletion compiler/rustc_borrowck/src/dataflow.rs
Original file line number Diff line number Diff line change
@@ -301,6 +301,7 @@ struct PoloniusOutOfScopePrecomputer<'a, 'tcx> {
loans_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
}

#[expect(dead_code)]
impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
fn compute(
body: &Body<'tcx>,
@@ -476,11 +477,18 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
if !tcx.sess.opts.unstable_opts.polonius.is_next_enabled() {
calculate_borrows_out_of_scope_at_location(body, regioncx, borrow_set)
} else {
PoloniusOutOfScopePrecomputer::compute(body, regioncx, borrow_set)
unimplemented!() // This should probably be removed.
};
Borrows { tcx, body, borrow_set, borrows_out_of_scope_at_location }
}

/// A dummy `Borrows` with no useful information.
///
/// Used for Polonius which doesn't need this.
pub fn dummy(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, borrow_set: &'a BorrowSet<'tcx>) -> Self {
Borrows { tcx, body, borrow_set, borrows_out_of_scope_at_location: Default::default() }
}

/// Add all borrows to the kill set, if those borrows are out of scope at `location`.
/// That means they went out of a nonlexical scope
fn kill_loans_out_of_scope_at_location(
@@ -563,6 +571,10 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
const NAME: &'static str = "borrows";

fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
if !self.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() {
return DenseBitSet::new_empty(0);
}

// bottom = nothing is reserved or activated yet;
DenseBitSet::new_empty(self.borrow_set.len())
}
@@ -578,6 +590,10 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
_statement: &mir::Statement<'tcx>,
location: Location,
) {
if !self.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() {
return;
}

self.kill_loans_out_of_scope_at_location(state, location);
}

@@ -587,6 +603,10 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
stmt: &mir::Statement<'tcx>,
location: Location,
) {
if !self.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() {
return;
}

match &stmt.kind {
mir::StatementKind::Assign(box (lhs, rhs)) => {
if let mir::Rvalue::Ref(_, _, place) = rhs {
@@ -636,6 +656,10 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
_terminator: &mir::Terminator<'tcx>,
location: Location,
) {
if !self.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() {
return;
}

self.kill_loans_out_of_scope_at_location(state, location);
}

@@ -645,6 +669,10 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
terminator: &'mir mir::Terminator<'tcx>,
_location: Location,
) -> TerminatorEdges<'mir, 'tcx> {
if !self.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() {
return terminator.edges();
}

if let mir::TerminatorKind::InlineAsm { operands, .. } = &terminator.kind {
for op in operands {
if let mir::InlineAsmOperand::Out { place: Some(place), .. }
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
Original file line number Diff line number Diff line change
@@ -632,8 +632,8 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
// We want to focus on relevant live locals in diagnostics, so when polonius is enabled, we
// ensure that we don't emit live boring locals as explanations.
let is_local_boring = |local| {
if let Some(polonius_diagnostics) = self.polonius_diagnostics {
polonius_diagnostics.boring_nll_locals.contains(&local)
if let Some(polonius) = &self.polonius {
polonius.pcx.is_boring_local(local)
} else {
assert!(!tcx.sess.opts.unstable_opts.polonius.is_next_enabled());

Loading