Skip to content
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

Take MIR dataflow analyses by mutable reference #108293

Merged
merged 1 commit into from
Jun 9, 2023
Merged
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
18 changes: 9 additions & 9 deletions compiler/rustc_borrowck/src/dataflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ macro_rules! impl_visitable {
}

fn reconstruct_before_statement_effect(
&self,
&mut self,
state: &mut Self::FlowState,
stmt: &mir::Statement<'tcx>,
loc: Location,
Expand All @@ -69,7 +69,7 @@ macro_rules! impl_visitable {
}

fn reconstruct_statement_effect(
&self,
&mut self,
state: &mut Self::FlowState,
stmt: &mir::Statement<'tcx>,
loc: Location,
Expand All @@ -79,7 +79,7 @@ macro_rules! impl_visitable {
}

fn reconstruct_before_terminator_effect(
&self,
&mut self,
state: &mut Self::FlowState,
term: &mir::Terminator<'tcx>,
loc: Location,
Expand All @@ -89,7 +89,7 @@ macro_rules! impl_visitable {
}

fn reconstruct_terminator_effect(
&self,
&mut self,
state: &mut Self::FlowState,
term: &mir::Terminator<'tcx>,
loc: Location,
Expand Down Expand Up @@ -341,7 +341,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
type Idx = BorrowIndex;

fn before_statement_effect(
&self,
&mut self,
trans: &mut impl GenKill<Self::Idx>,
_statement: &mir::Statement<'tcx>,
location: Location,
Expand All @@ -350,7 +350,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
}

fn statement_effect(
&self,
&mut self,
trans: &mut impl GenKill<Self::Idx>,
stmt: &mir::Statement<'tcx>,
location: Location,
Expand Down Expand Up @@ -398,7 +398,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
}

fn before_terminator_effect(
&self,
&mut self,
trans: &mut impl GenKill<Self::Idx>,
_terminator: &mir::Terminator<'tcx>,
location: Location,
Expand All @@ -407,7 +407,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
}

fn terminator_effect(
&self,
&mut self,
trans: &mut impl GenKill<Self::Idx>,
terminator: &mir::Terminator<'tcx>,
_location: Location,
Expand All @@ -424,7 +424,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
}

fn call_return_effect(
&self,
&mut self,
_trans: &mut impl GenKill<Self::Idx>,
_block: mir::BasicBlock,
_return_places: CallReturnPlaces<'_, 'tcx>,
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ fn do_mir_borrowck<'tcx>(
// Compute and report region errors, if any.
mbcx.report_region_errors(nll_errors);

let results = BorrowckResults {
let mut results = BorrowckResults {
ever_inits: flow_ever_inits,
uninits: flow_uninits,
borrows: flow_borrows,
Expand All @@ -383,7 +383,7 @@ fn do_mir_borrowck<'tcx>(
rustc_mir_dataflow::visit_results(
body,
traversal::reverse_postorder(body).map(|(bb, _)| bb),
&results,
&mut results,
&mut mbcx,
);

Expand Down Expand Up @@ -618,11 +618,12 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
// 2. loans made in overlapping scopes do not conflict
// 3. assignments do not affect things loaned out as immutable
// 4. moves do not affect things loaned out in any way
impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx> {
impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorrowckCtxt<'cx, 'tcx> {
type FlowState = Flows<'cx, 'tcx>;

fn visit_statement_before_primary_effect(
&mut self,
_results: &R,
flow_state: &Flows<'cx, 'tcx>,
stmt: &'cx Statement<'tcx>,
location: Location,
Expand Down Expand Up @@ -692,6 +693,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx

fn visit_terminator_before_primary_effect(
&mut self,
_results: &R,
flow_state: &Flows<'cx, 'tcx>,
term: &'cx Terminator<'tcx>,
loc: Location,
Expand Down Expand Up @@ -800,6 +802,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx

fn visit_terminator_after_primary_effect(
&mut self,
_results: &R,
flow_state: &Flows<'cx, 'tcx>,
term: &'cx Terminator<'tcx>,
loc: Location,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ where
Q: Qualif,
{
fn apply_statement_effect(
&self,
&mut self,
state: &mut Self::Domain,
statement: &mir::Statement<'tcx>,
location: Location,
Expand All @@ -346,7 +346,7 @@ where
}

fn apply_terminator_effect(
&self,
&mut self,
state: &mut Self::Domain,
terminator: &mir::Terminator<'tcx>,
location: Location,
Expand All @@ -355,7 +355,7 @@ where
}

fn apply_call_return_effect(
&self,
&mut self,
state: &mut Self::Domain,
block: BasicBlock,
return_places: CallReturnPlaces<'_, 'tcx>,
Expand Down
112 changes: 97 additions & 15 deletions compiler/rustc_mir_dataflow/src/framework/cursor.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,60 @@
//! Random access inspection of the results of a dataflow analysis.

use crate::framework::BitSetExt;
use crate::{framework::BitSetExt, CloneAnalysis};

use std::borrow::Borrow;
use std::borrow::{Borrow, BorrowMut};
use std::cmp::Ordering;

#[cfg(debug_assertions)]
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::{self, BasicBlock, Location};

use super::{Analysis, Direction, Effect, EffectIndex, Results};
use super::{Analysis, Direction, Effect, EffectIndex, EntrySets, Results, ResultsCloned};

// `AnalysisResults` is needed as an impl such as the following has an unconstrained type
// parameter:
// ```
// impl<'tcx, A, E, R> ResultsCursor<'_, 'tcx, A, R>
// where
// A: Analysis<'tcx>,
// E: Borrow<EntrySets<'tcx, A>>,
// R: Results<'tcx, A, E>,
// {}
// ```

/// A type representing the analysis results consumed by a `ResultsCursor`.
pub trait AnalysisResults<'tcx, A>: BorrowMut<Results<'tcx, A, Self::EntrySets>>
where
A: Analysis<'tcx>,
{
/// The type containing the entry sets for this `Results` type.
///
/// Should be either `EntrySets<'tcx, A>` or `&EntrySets<'tcx, A>`.
type EntrySets: Borrow<EntrySets<'tcx, A>>;
}
impl<'tcx, A, E> AnalysisResults<'tcx, A> for Results<'tcx, A, E>
where
A: Analysis<'tcx>,
E: Borrow<EntrySets<'tcx, A>>,
{
type EntrySets = E;
}
impl<'a, 'tcx, A, E> AnalysisResults<'tcx, A> for &'a mut Results<'tcx, A, E>
where
A: Analysis<'tcx>,
E: Borrow<EntrySets<'tcx, A>>,
{
type EntrySets = E;
}

/// A `ResultsCursor` that borrows the underlying `Results`.
pub type ResultsRefCursor<'a, 'mir, 'tcx, A> = ResultsCursor<'mir, 'tcx, A, &'a Results<'tcx, A>>;
pub type ResultsRefCursor<'res, 'mir, 'tcx, A> =
ResultsCursor<'mir, 'tcx, A, &'res mut Results<'tcx, A>>;

/// A `ResultsCursor` which uses a cloned `Analysis` while borrowing the underlying `Results`. This
/// allows multiple cursors over the same `Results`.
pub type ResultsClonedCursor<'res, 'mir, 'tcx, A> =
ResultsCursor<'mir, 'tcx, A, ResultsCloned<'res, 'tcx, A>>;

/// Allows random access inspection of the results of a dataflow analysis.
///
Expand Down Expand Up @@ -45,7 +87,38 @@ where
impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R>
where
A: Analysis<'tcx>,
R: Borrow<Results<'tcx, A>>,
{
/// Returns the dataflow state at the current location.
pub fn get(&self) -> &A::Domain {
&self.state
}

/// Returns the body this analysis was run on.
pub fn body(&self) -> &'mir mir::Body<'tcx> {
self.body
}

/// Unwraps this cursor, returning the underlying `Results`.
pub fn into_results(self) -> R {
self.results
}
}

impl<'res, 'mir, 'tcx, A> ResultsCursor<'mir, 'tcx, A, ResultsCloned<'res, 'tcx, A>>
where
A: Analysis<'tcx> + CloneAnalysis,
{
/// Creates a new cursor over the same `Results`. Note that the cursor's position is *not*
/// copied.
pub fn new_cursor(&self) -> Self {
Self::new(self.body, self.results.reclone_analysis())
}
}

impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R>
where
A: Analysis<'tcx>,
R: AnalysisResults<'tcx, A>,
{
/// Returns a new cursor that can inspect `results`.
pub fn new(body: &'mir mir::Body<'tcx>, results: R) -> Self {
Expand Down Expand Up @@ -74,18 +147,28 @@ where
}

/// Returns the underlying `Results`.
pub fn results(&self) -> &Results<'tcx, A> {
&self.results.borrow()
pub fn results(&mut self) -> &Results<'tcx, A, R::EntrySets> {
self.results.borrow()
}

/// Returns the underlying `Results`.
pub fn mut_results(&mut self) -> &mut Results<'tcx, A, R::EntrySets> {
self.results.borrow_mut()
}

/// Returns the `Analysis` used to generate the underlying `Results`.
pub fn analysis(&self) -> &A {
&self.results.borrow().analysis
}

/// Returns the dataflow state at the current location.
pub fn get(&self) -> &A::Domain {
&self.state
/// Returns the `Analysis` used to generate the underlying `Results`.
pub fn mut_analysis(&mut self) -> &mut A {
&mut self.results.borrow_mut().analysis
}

/// Returns both the dataflow state at the current location and the `Analysis`.
pub fn get_with_analysis(&mut self) -> (&A::Domain, &mut A) {
(&self.state, &mut self.results.borrow_mut().analysis)
}

/// Resets the cursor to hold the entry set for the given basic block.
Expand All @@ -97,7 +180,7 @@ where
#[cfg(debug_assertions)]
assert!(self.reachable_blocks.contains(block));

self.state.clone_from(&self.results.borrow().entry_set_for_block(block));
self.state.clone_from(self.results.borrow().entry_set_for_block(block));
self.pos = CursorPosition::block_entry(block);
self.state_needs_reset = false;
}
Expand Down Expand Up @@ -186,7 +269,7 @@ where
)
};

let analysis = &self.results.borrow().analysis;
let analysis = &mut self.results.borrow_mut().analysis;
let target_effect_index = effect.at_index(target.statement_index);

A::Direction::apply_effects_in_range(
Expand All @@ -205,8 +288,8 @@ where
///
/// This can be used, e.g., to apply the call return effect directly to the cursor without
/// creating an extra copy of the dataflow state.
pub fn apply_custom_effect(&mut self, f: impl FnOnce(&A, &mut A::Domain)) {
f(&self.results.borrow().analysis, &mut self.state);
pub fn apply_custom_effect(&mut self, f: impl FnOnce(&mut A, &mut A::Domain)) {
f(&mut self.results.borrow_mut().analysis, &mut self.state);
self.state_needs_reset = true;
}
}
Expand All @@ -215,7 +298,6 @@ impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R>
where
A: crate::GenKillAnalysis<'tcx>,
A::Domain: BitSetExt<A::Idx>,
R: Borrow<Results<'tcx, A>>,
{
pub fn contains(&self, elem: A::Idx) -> bool {
self.get().contains(elem)
Expand Down
Loading