Auto merge of #5198 - sinkuu:redundant_clone_df, r=flip1995
redundant_clone: Migrate to new dataflow framework Migration to [the new dataflow framework](https://github.com/rust-lang/rust/pull/65672) is ongoing in rustc. This PR updates the dataflow impl in `redundant_clone` lint. --- changelog: none
This commit is contained in:
commit
5fbec44fd9
1 changed files with 41 additions and 50 deletions
|
@ -15,9 +15,8 @@ use rustc_hir::intravisit::FnKind;
|
||||||
use rustc_hir::{def_id, Body, FnDecl, HirId};
|
use rustc_hir::{def_id, Body, FnDecl, HirId};
|
||||||
use rustc_index::bit_set::{BitSet, HybridBitSet};
|
use rustc_index::bit_set::{BitSet, HybridBitSet};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_mir::dataflow::{
|
use rustc_mir::dataflow::generic::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis, ResultsCursor};
|
||||||
do_dataflow, BitDenotation, BottomValue, DataflowResults, DataflowResultsCursor, DebugFormatted, GenKillSet,
|
use rustc_mir::dataflow::BottomValue;
|
||||||
};
|
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::source_map::{BytePos, Span};
|
use rustc_span::source_map::{BytePos, Span};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
@ -83,16 +82,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone {
|
||||||
let mir = cx.tcx.optimized_mir(def_id);
|
let mir = cx.tcx.optimized_mir(def_id);
|
||||||
let mir_read_only = mir.unwrap_read_only();
|
let mir_read_only = mir.unwrap_read_only();
|
||||||
|
|
||||||
let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
|
let maybe_storage_live_result = MaybeStorageLive
|
||||||
let maybe_storage_live_result = do_dataflow(
|
.into_engine(cx.tcx, mir, def_id)
|
||||||
cx.tcx,
|
.iterate_to_fixpoint()
|
||||||
mir,
|
.into_results_cursor(mir);
|
||||||
def_id,
|
|
||||||
&[],
|
|
||||||
&dead_unwinds,
|
|
||||||
MaybeStorageLive::new(mir),
|
|
||||||
|bd, p| DebugFormatted::new(&bd.body.local_decls[p]),
|
|
||||||
);
|
|
||||||
let mut possible_borrower = {
|
let mut possible_borrower = {
|
||||||
let mut vis = PossibleBorrowerVisitor::new(cx, mir);
|
let mut vis = PossibleBorrowerVisitor::new(cx, mir);
|
||||||
vis.visit_body(mir_read_only);
|
vis.visit_body(mir_read_only);
|
||||||
|
@ -377,34 +370,25 @@ impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor {
|
||||||
|
|
||||||
/// Determines liveness of each local purely based on `StorageLive`/`Dead`.
|
/// Determines liveness of each local purely based on `StorageLive`/`Dead`.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct MaybeStorageLive<'a, 'tcx> {
|
struct MaybeStorageLive;
|
||||||
body: &'a mir::Body<'tcx>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx> MaybeStorageLive<'a, 'tcx> {
|
impl<'tcx> AnalysisDomain<'tcx> for MaybeStorageLive {
|
||||||
fn new(body: &'a mir::Body<'tcx>) -> Self {
|
|
||||||
MaybeStorageLive { body }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> {
|
|
||||||
type Idx = mir::Local;
|
type Idx = mir::Local;
|
||||||
fn name() -> &'static str {
|
const NAME: &'static str = "maybe_storage_live";
|
||||||
"maybe_storage_live"
|
|
||||||
}
|
fn bits_per_block(&self, body: &mir::Body<'tcx>) -> usize {
|
||||||
fn bits_per_block(&self) -> usize {
|
body.local_decls.len()
|
||||||
self.body.local_decls.len()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_block_effect(&self, on_entry: &mut BitSet<mir::Local>) {
|
fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut BitSet<Self::Idx>) {
|
||||||
for arg in self.body.args_iter() {
|
for arg in body.args_iter() {
|
||||||
on_entry.insert(arg);
|
state.insert(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn statement_effect(&self, trans: &mut GenKillSet<mir::Local>, loc: mir::Location) {
|
impl<'tcx> GenKillAnalysis<'tcx> for MaybeStorageLive {
|
||||||
let stmt = &self.body[loc.block].statements[loc.statement_index];
|
fn statement_effect(&self, trans: &mut impl GenKill<Self::Idx>, stmt: &mir::Statement<'tcx>, _: mir::Location) {
|
||||||
|
|
||||||
match stmt.kind {
|
match stmt.kind {
|
||||||
mir::StatementKind::StorageLive(l) => trans.gen(l),
|
mir::StatementKind::StorageLive(l) => trans.gen(l),
|
||||||
mir::StatementKind::StorageDead(l) => trans.kill(l),
|
mir::StatementKind::StorageDead(l) => trans.kill(l),
|
||||||
|
@ -412,20 +396,27 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn terminator_effect(&self, _trans: &mut GenKillSet<mir::Local>, _loc: mir::Location) {}
|
fn terminator_effect(
|
||||||
|
|
||||||
fn propagate_call_return(
|
|
||||||
&self,
|
&self,
|
||||||
_in_out: &mut BitSet<mir::Local>,
|
_trans: &mut impl GenKill<Self::Idx>,
|
||||||
_call_bb: mir::BasicBlock,
|
_terminator: &mir::Terminator<'tcx>,
|
||||||
_dest_bb: mir::BasicBlock,
|
_loc: mir::Location,
|
||||||
_dest_place: &mir::Place<'tcx>,
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call_return_effect(
|
||||||
|
&self,
|
||||||
|
_in_out: &mut impl GenKill<Self::Idx>,
|
||||||
|
_block: mir::BasicBlock,
|
||||||
|
_func: &mir::Operand<'tcx>,
|
||||||
|
_args: &[mir::Operand<'tcx>],
|
||||||
|
_return_place: &mir::Place<'tcx>,
|
||||||
) {
|
) {
|
||||||
// Nothing to do when a call returns successfully
|
// Nothing to do when a call returns successfully
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> {
|
impl BottomValue for MaybeStorageLive {
|
||||||
/// bottom = dead
|
/// bottom = dead
|
||||||
const BOTTOM_VALUE: bool = false;
|
const BOTTOM_VALUE: bool = false;
|
||||||
}
|
}
|
||||||
|
@ -451,8 +442,8 @@ impl<'a, 'tcx> PossibleBorrowerVisitor<'a, 'tcx> {
|
||||||
fn into_map(
|
fn into_map(
|
||||||
self,
|
self,
|
||||||
cx: &LateContext<'a, 'tcx>,
|
cx: &LateContext<'a, 'tcx>,
|
||||||
maybe_live: DataflowResults<'tcx, MaybeStorageLive<'a, 'tcx>>,
|
maybe_live: ResultsCursor<'tcx, 'tcx, MaybeStorageLive>,
|
||||||
) -> PossibleBorrower<'a, 'tcx> {
|
) -> PossibleBorrowerMap<'a, 'tcx> {
|
||||||
let mut map = FxHashMap::default();
|
let mut map = FxHashMap::default();
|
||||||
for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) {
|
for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) {
|
||||||
if is_copy(cx, self.body.local_decls[row].ty) {
|
if is_copy(cx, self.body.local_decls[row].ty) {
|
||||||
|
@ -475,9 +466,9 @@ impl<'a, 'tcx> PossibleBorrowerVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let bs = BitSet::new_empty(self.body.local_decls.len());
|
let bs = BitSet::new_empty(self.body.local_decls.len());
|
||||||
PossibleBorrower {
|
PossibleBorrowerMap {
|
||||||
map,
|
map,
|
||||||
maybe_live: DataflowResultsCursor::new(maybe_live, self.body),
|
maybe_live,
|
||||||
bitset: (bs.clone(), bs),
|
bitset: (bs.clone(), bs),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -557,18 +548,18 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Result of `PossibleBorrowerVisitor`.
|
/// Result of `PossibleBorrowerVisitor`.
|
||||||
struct PossibleBorrower<'a, 'tcx> {
|
struct PossibleBorrowerMap<'a, 'tcx> {
|
||||||
/// Mapping `Local -> its possible borrowers`
|
/// Mapping `Local -> its possible borrowers`
|
||||||
map: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
|
map: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
|
||||||
maybe_live: DataflowResultsCursor<'a, 'tcx, MaybeStorageLive<'a, 'tcx>>,
|
maybe_live: ResultsCursor<'a, 'tcx, MaybeStorageLive>,
|
||||||
// Caches to avoid allocation of `BitSet` on every query
|
// Caches to avoid allocation of `BitSet` on every query
|
||||||
bitset: (BitSet<mir::Local>, BitSet<mir::Local>),
|
bitset: (BitSet<mir::Local>, BitSet<mir::Local>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PossibleBorrower<'_, '_> {
|
impl PossibleBorrowerMap<'_, '_> {
|
||||||
/// Returns true if the set of borrowers of `borrowed` living at `at` matches with `borrowers`.
|
/// Returns true if the set of borrowers of `borrowed` living at `at` matches with `borrowers`.
|
||||||
fn only_borrowers(&mut self, borrowers: &[mir::Local], borrowed: mir::Local, at: mir::Location) -> bool {
|
fn only_borrowers(&mut self, borrowers: &[mir::Local], borrowed: mir::Local, at: mir::Location) -> bool {
|
||||||
self.maybe_live.seek(at);
|
self.maybe_live.seek_after(at);
|
||||||
|
|
||||||
self.bitset.0.clear();
|
self.bitset.0.clear();
|
||||||
let maybe_live = &mut self.maybe_live;
|
let maybe_live = &mut self.maybe_live;
|
||||||
|
|
Loading…
Add table
Reference in a new issue