mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Merge AnalysisDomain
into Analysis
.
With `GenKillAnalysis` gone, there is no need for them to be separate.
This commit is contained in:
parent
4dc1b4d0b1
commit
ba13775319
@ -7,7 +7,7 @@ use rustc_middle::mir::{
|
|||||||
use rustc_middle::ty::{RegionVid, TyCtxt};
|
use rustc_middle::ty::{RegionVid, TyCtxt};
|
||||||
use rustc_mir_dataflow::fmt::DebugWithContext;
|
use rustc_mir_dataflow::fmt::DebugWithContext;
|
||||||
use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
|
use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
|
||||||
use rustc_mir_dataflow::{Analysis, AnalysisDomain, Forward, GenKill, Results, ResultsVisitable};
|
use rustc_mir_dataflow::{Analysis, Forward, GenKill, Results, ResultsVisitable};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::{BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, places_conflict};
|
use crate::{BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, places_conflict};
|
||||||
@ -22,9 +22,9 @@ pub(crate) struct BorrowckResults<'a, 'tcx> {
|
|||||||
/// The transient state of the dataflow analyses used by the borrow checker.
|
/// The transient state of the dataflow analyses used by the borrow checker.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct BorrowckDomain<'a, 'tcx> {
|
pub(crate) struct BorrowckDomain<'a, 'tcx> {
|
||||||
pub(crate) borrows: <Borrows<'a, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
pub(crate) borrows: <Borrows<'a, 'tcx> as Analysis<'tcx>>::Domain,
|
||||||
pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain,
|
||||||
pub(crate) ever_inits: <EverInitializedPlaces<'a, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
pub(crate) ever_inits: <EverInitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'tcx> {
|
impl<'a, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'tcx> {
|
||||||
@ -427,7 +427,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
|
|||||||
/// That means they went out of a nonlexical scope
|
/// That means they went out of a nonlexical scope
|
||||||
fn kill_loans_out_of_scope_at_location(
|
fn kill_loans_out_of_scope_at_location(
|
||||||
&self,
|
&self,
|
||||||
trans: &mut <Self as AnalysisDomain<'tcx>>::Domain,
|
trans: &mut <Self as Analysis<'tcx>>::Domain,
|
||||||
location: Location,
|
location: Location,
|
||||||
) {
|
) {
|
||||||
// NOTE: The state associated with a given `location`
|
// NOTE: The state associated with a given `location`
|
||||||
@ -449,7 +449,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
|
|||||||
/// Kill any borrows that conflict with `place`.
|
/// Kill any borrows that conflict with `place`.
|
||||||
fn kill_borrows_on_place(
|
fn kill_borrows_on_place(
|
||||||
&self,
|
&self,
|
||||||
trans: &mut <Self as AnalysisDomain<'tcx>>::Domain,
|
trans: &mut <Self as Analysis<'tcx>>::Domain,
|
||||||
place: Place<'tcx>,
|
place: Place<'tcx>,
|
||||||
) {
|
) {
|
||||||
debug!("kill_borrows_on_place: place={:?}", place);
|
debug!("kill_borrows_on_place: place={:?}", place);
|
||||||
@ -490,7 +490,14 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
|
/// Forward dataflow computation of the set of borrows that are in scope at a particular location.
|
||||||
|
/// - we gen the introduced loans
|
||||||
|
/// - we kill loans on locals going out of (regular) scope
|
||||||
|
/// - we kill the loans going out of their region's NLL scope: in NLL terms, the frontier where a
|
||||||
|
/// region stops containing the CFG points reachable from the issuing location.
|
||||||
|
/// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of
|
||||||
|
/// `a.b.c` when `a` is overwritten.
|
||||||
|
impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
|
||||||
type Domain = BitSet<BorrowIndex>;
|
type Domain = BitSet<BorrowIndex>;
|
||||||
|
|
||||||
const NAME: &'static str = "borrows";
|
const NAME: &'static str = "borrows";
|
||||||
@ -504,16 +511,7 @@ impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
|
|||||||
// no borrows of code region_scopes have been taken prior to
|
// no borrows of code region_scopes have been taken prior to
|
||||||
// function execution, so this method has no effect.
|
// function execution, so this method has no effect.
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Forward dataflow computation of the set of borrows that are in scope at a particular location.
|
|
||||||
/// - we gen the introduced loans
|
|
||||||
/// - we kill loans on locals going out of (regular) scope
|
|
||||||
/// - we kill the loans going out of their region's NLL scope: in NLL terms, the frontier where a
|
|
||||||
/// region stops containing the CFG points reachable from the issuing location.
|
|
||||||
/// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of
|
|
||||||
/// `a.b.c` when `a` is overwritten.
|
|
||||||
impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
|
|
||||||
fn apply_before_statement_effect(
|
fn apply_before_statement_effect(
|
||||||
&mut self,
|
&mut self,
|
||||||
trans: &mut Self::Domain,
|
trans: &mut Self::Domain,
|
||||||
|
@ -11,7 +11,7 @@ use rustc_middle::mir::{
|
|||||||
self, BasicBlock, CallReturnPlaces, Local, Location, Statement, StatementKind, TerminatorEdges,
|
self, BasicBlock, CallReturnPlaces, Local, Location, Statement, StatementKind, TerminatorEdges,
|
||||||
};
|
};
|
||||||
use rustc_mir_dataflow::fmt::DebugWithContext;
|
use rustc_mir_dataflow::fmt::DebugWithContext;
|
||||||
use rustc_mir_dataflow::{Analysis, AnalysisDomain, JoinSemiLattice};
|
use rustc_mir_dataflow::{Analysis, JoinSemiLattice};
|
||||||
|
|
||||||
use super::{ConstCx, Qualif, qualifs};
|
use super::{ConstCx, Qualif, qualifs};
|
||||||
|
|
||||||
@ -310,7 +310,7 @@ impl JoinSemiLattice for State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, Q> AnalysisDomain<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
|
impl<'tcx, Q> Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
|
||||||
where
|
where
|
||||||
Q: Qualif,
|
Q: Qualif,
|
||||||
{
|
{
|
||||||
@ -328,12 +328,7 @@ where
|
|||||||
fn initialize_start_block(&self, _body: &mir::Body<'tcx>, state: &mut Self::Domain) {
|
fn initialize_start_block(&self, _body: &mir::Body<'tcx>, state: &mut Self::Domain) {
|
||||||
self.transfer_function(state).initialize_state();
|
self.transfer_function(state).initialize_state();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx, Q> Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
|
|
||||||
where
|
|
||||||
Q: Qualif,
|
|
||||||
{
|
|
||||||
fn apply_statement_effect(
|
fn apply_statement_effect(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut Self::Domain,
|
state: &mut Self::Domain,
|
||||||
|
@ -16,14 +16,13 @@ use {rustc_ast as ast, rustc_graphviz as dot};
|
|||||||
|
|
||||||
use super::fmt::DebugWithContext;
|
use super::fmt::DebugWithContext;
|
||||||
use super::{
|
use super::{
|
||||||
Analysis, AnalysisDomain, Direction, JoinSemiLattice, ResultsCursor, ResultsVisitor, graphviz,
|
Analysis, Direction, JoinSemiLattice, ResultsCursor, ResultsVisitor, graphviz, visit_results,
|
||||||
visit_results,
|
|
||||||
};
|
};
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter,
|
DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter,
|
||||||
};
|
};
|
||||||
|
|
||||||
type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as AnalysisDomain<'tcx>>::Domain>;
|
type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as Analysis<'tcx>>::Domain>;
|
||||||
|
|
||||||
/// A dataflow analysis that has converged to fixpoint.
|
/// A dataflow analysis that has converged to fixpoint.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -89,11 +89,26 @@ impl<T: Idx> BitSetExt<T> for ChunkedBitSet<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Defines the domain of a dataflow problem.
|
/// A dataflow problem with an arbitrarily complex transfer function.
|
||||||
///
|
///
|
||||||
/// This trait specifies the lattice on which this analysis operates (the domain) as well as its
|
/// This trait specifies the lattice on which this analysis operates (the domain), its
|
||||||
/// initial value at the entry point of each basic block.
|
/// initial value at the entry point of each basic block, and various operations.
|
||||||
pub trait AnalysisDomain<'tcx> {
|
///
|
||||||
|
/// # Convergence
|
||||||
|
///
|
||||||
|
/// When implementing this trait it's possible to choose a transfer function such that the analysis
|
||||||
|
/// does not reach fixpoint. To guarantee convergence, your transfer functions must maintain the
|
||||||
|
/// following invariant:
|
||||||
|
///
|
||||||
|
/// > If the dataflow state **before** some point in the program changes to be greater
|
||||||
|
/// than the prior state **before** that point, the dataflow state **after** that point must
|
||||||
|
/// also change to be greater than the prior state **after** that point.
|
||||||
|
///
|
||||||
|
/// This invariant guarantees that the dataflow state at a given point in the program increases
|
||||||
|
/// monotonically until fixpoint is reached. Note that this monotonicity requirement only applies
|
||||||
|
/// to the same point in the program at different points in time. The dataflow state at a given
|
||||||
|
/// point in the program may or may not be greater than the state at any preceding point.
|
||||||
|
pub trait Analysis<'tcx> {
|
||||||
/// The type that holds the dataflow state at any given point in the program.
|
/// The type that holds the dataflow state at any given point in the program.
|
||||||
type Domain: Clone + JoinSemiLattice;
|
type Domain: Clone + JoinSemiLattice;
|
||||||
|
|
||||||
@ -118,25 +133,7 @@ pub trait AnalysisDomain<'tcx> {
|
|||||||
// block where control flow could exit the MIR body (e.g., those terminated with `return` or
|
// block where control flow could exit the MIR body (e.g., those terminated with `return` or
|
||||||
// `resume`). It's not obvious how to handle `yield` points in coroutines, however.
|
// `resume`). It's not obvious how to handle `yield` points in coroutines, however.
|
||||||
fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain);
|
fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain);
|
||||||
}
|
|
||||||
|
|
||||||
/// A dataflow problem with an arbitrarily complex transfer function.
|
|
||||||
///
|
|
||||||
/// # Convergence
|
|
||||||
///
|
|
||||||
/// When implementing this trait it's possible to choose a transfer function such that the analysis
|
|
||||||
/// does not reach fixpoint. To guarantee convergence, your transfer functions must maintain the
|
|
||||||
/// following invariant:
|
|
||||||
///
|
|
||||||
/// > If the dataflow state **before** some point in the program changes to be greater
|
|
||||||
/// than the prior state **before** that point, the dataflow state **after** that point must
|
|
||||||
/// also change to be greater than the prior state **after** that point.
|
|
||||||
///
|
|
||||||
/// This invariant guarantees that the dataflow state at a given point in the program increases
|
|
||||||
/// monotonically until fixpoint is reached. Note that this monotonicity requirement only applies
|
|
||||||
/// to the same point in the program at different points in time. The dataflow state at a given
|
|
||||||
/// point in the program may or may not be greater than the state at any preceding point.
|
|
||||||
pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
|
|
||||||
/// Updates the current dataflow state with the effect of evaluating a statement.
|
/// Updates the current dataflow state with the effect of evaluating a statement.
|
||||||
fn apply_statement_effect(
|
fn apply_statement_effect(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -154,7 +154,7 @@ impl<D: Direction> MockAnalysis<'_, D> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, D: Direction> AnalysisDomain<'tcx> for MockAnalysis<'tcx, D> {
|
impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> {
|
||||||
type Domain = BitSet<usize>;
|
type Domain = BitSet<usize>;
|
||||||
type Direction = D;
|
type Direction = D;
|
||||||
|
|
||||||
@ -167,9 +167,7 @@ impl<'tcx, D: Direction> AnalysisDomain<'tcx> for MockAnalysis<'tcx, D> {
|
|||||||
fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) {
|
fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) {
|
||||||
unimplemented!("This is never called since `MockAnalysis` is never iterated to fixpoint");
|
unimplemented!("This is never called since `MockAnalysis` is never iterated to fixpoint");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> {
|
|
||||||
fn apply_statement_effect(
|
fn apply_statement_effect(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut Self::Domain,
|
state: &mut Self::Domain,
|
||||||
|
@ -2,7 +2,7 @@ use rustc_index::bit_set::BitSet;
|
|||||||
use rustc_middle::mir::visit::Visitor;
|
use rustc_middle::mir::visit::Visitor;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
|
|
||||||
use crate::{Analysis, AnalysisDomain, GenKill};
|
use crate::{Analysis, GenKill};
|
||||||
|
|
||||||
/// A dataflow analysis that tracks whether a pointer or reference could possibly exist that points
|
/// A dataflow analysis that tracks whether a pointer or reference could possibly exist that points
|
||||||
/// to a given local. This analysis ignores fake borrows, so it should not be used by
|
/// to a given local. This analysis ignores fake borrows, so it should not be used by
|
||||||
@ -20,7 +20,7 @@ impl MaybeBorrowedLocals {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> AnalysisDomain<'tcx> for MaybeBorrowedLocals {
|
impl<'tcx> Analysis<'tcx> for MaybeBorrowedLocals {
|
||||||
type Domain = BitSet<Local>;
|
type Domain = BitSet<Local>;
|
||||||
const NAME: &'static str = "maybe_borrowed_locals";
|
const NAME: &'static str = "maybe_borrowed_locals";
|
||||||
|
|
||||||
@ -32,9 +32,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeBorrowedLocals {
|
|||||||
fn initialize_start_block(&self, _: &Body<'tcx>, _: &mut Self::Domain) {
|
fn initialize_start_block(&self, _: &Body<'tcx>, _: &mut Self::Domain) {
|
||||||
// No locals are aliased on function entry
|
// No locals are aliased on function entry
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Analysis<'tcx> for MaybeBorrowedLocals {
|
|
||||||
fn apply_statement_effect(
|
fn apply_statement_effect(
|
||||||
&mut self,
|
&mut self,
|
||||||
trans: &mut Self::Domain,
|
trans: &mut Self::Domain,
|
||||||
|
@ -11,9 +11,8 @@ use crate::elaborate_drops::DropFlagState;
|
|||||||
use crate::framework::SwitchIntEdgeEffects;
|
use crate::framework::SwitchIntEdgeEffects;
|
||||||
use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex};
|
use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex};
|
||||||
use crate::{
|
use crate::{
|
||||||
Analysis, AnalysisDomain, GenKill, MaybeReachable, drop_flag_effects,
|
Analysis, GenKill, MaybeReachable, drop_flag_effects, drop_flag_effects_for_function_entry,
|
||||||
drop_flag_effects_for_function_entry, drop_flag_effects_for_location, lattice,
|
drop_flag_effects_for_location, lattice, on_all_children_bits, on_lookup_result_bits,
|
||||||
on_all_children_bits, on_lookup_result_bits,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// `MaybeInitializedPlaces` tracks all places that might be
|
/// `MaybeInitializedPlaces` tracks all places that might be
|
||||||
@ -270,7 +269,7 @@ impl<'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'_, 'tcx> {
|
|||||||
|
|
||||||
impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
|
impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
|
||||||
fn update_bits(
|
fn update_bits(
|
||||||
trans: &mut <Self as AnalysisDomain<'tcx>>::Domain,
|
trans: &mut <Self as Analysis<'tcx>>::Domain,
|
||||||
path: MovePathIndex,
|
path: MovePathIndex,
|
||||||
state: DropFlagState,
|
state: DropFlagState,
|
||||||
) {
|
) {
|
||||||
@ -283,7 +282,7 @@ impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
|
|||||||
|
|
||||||
impl<'tcx> MaybeUninitializedPlaces<'_, 'tcx> {
|
impl<'tcx> MaybeUninitializedPlaces<'_, 'tcx> {
|
||||||
fn update_bits(
|
fn update_bits(
|
||||||
trans: &mut <Self as AnalysisDomain<'tcx>>::Domain,
|
trans: &mut <Self as Analysis<'tcx>>::Domain,
|
||||||
path: MovePathIndex,
|
path: MovePathIndex,
|
||||||
state: DropFlagState,
|
state: DropFlagState,
|
||||||
) {
|
) {
|
||||||
@ -296,7 +295,7 @@ impl<'tcx> MaybeUninitializedPlaces<'_, 'tcx> {
|
|||||||
|
|
||||||
impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
|
impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
|
||||||
fn update_bits(
|
fn update_bits(
|
||||||
trans: &mut <Self as AnalysisDomain<'tcx>>::Domain,
|
trans: &mut <Self as Analysis<'tcx>>::Domain,
|
||||||
path: MovePathIndex,
|
path: MovePathIndex,
|
||||||
state: DropFlagState,
|
state: DropFlagState,
|
||||||
) {
|
) {
|
||||||
@ -307,7 +306,7 @@ impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
||||||
/// There can be many more `MovePathIndex` than there are locals in a MIR body.
|
/// There can be many more `MovePathIndex` than there are locals in a MIR body.
|
||||||
/// We use a chunked bitset to avoid paying too high a memory footprint.
|
/// We use a chunked bitset to avoid paying too high a memory footprint.
|
||||||
type Domain = MaybeReachable<ChunkedBitSet<MovePathIndex>>;
|
type Domain = MaybeReachable<ChunkedBitSet<MovePathIndex>>;
|
||||||
@ -327,9 +326,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
|||||||
state.gen_(path);
|
state.gen_(path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
|
||||||
fn apply_statement_effect(
|
fn apply_statement_effect(
|
||||||
&mut self,
|
&mut self,
|
||||||
trans: &mut Self::Domain,
|
trans: &mut Self::Domain,
|
||||||
@ -436,7 +433,7 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
|
impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
|
||||||
/// There can be many more `MovePathIndex` than there are locals in a MIR body.
|
/// There can be many more `MovePathIndex` than there are locals in a MIR body.
|
||||||
/// We use a chunked bitset to avoid paying too high a memory footprint.
|
/// We use a chunked bitset to avoid paying too high a memory footprint.
|
||||||
type Domain = ChunkedBitSet<MovePathIndex>;
|
type Domain = ChunkedBitSet<MovePathIndex>;
|
||||||
@ -458,9 +455,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
|
|||||||
state.remove(path);
|
state.remove(path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
|
|
||||||
fn apply_statement_effect(
|
fn apply_statement_effect(
|
||||||
&mut self,
|
&mut self,
|
||||||
trans: &mut Self::Domain,
|
trans: &mut Self::Domain,
|
||||||
@ -559,7 +554,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> AnalysisDomain<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
|
impl<'a, 'tcx> Analysis<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
|
||||||
/// Use set intersection as the join operator.
|
/// Use set intersection as the join operator.
|
||||||
type Domain = lattice::Dual<BitSet<MovePathIndex>>;
|
type Domain = lattice::Dual<BitSet<MovePathIndex>>;
|
||||||
|
|
||||||
@ -579,9 +574,7 @@ impl<'a, 'tcx> AnalysisDomain<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
|
|||||||
state.0.insert(path);
|
state.0.insert(path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Analysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> {
|
|
||||||
fn apply_statement_effect(
|
fn apply_statement_effect(
|
||||||
&mut self,
|
&mut self,
|
||||||
trans: &mut Self::Domain,
|
trans: &mut Self::Domain,
|
||||||
@ -625,7 +618,7 @@ impl<'tcx> Analysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> {
|
impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
|
||||||
/// There can be many more `InitIndex` than there are locals in a MIR body.
|
/// There can be many more `InitIndex` than there are locals in a MIR body.
|
||||||
/// We use a chunked bitset to avoid paying too high a memory footprint.
|
/// We use a chunked bitset to avoid paying too high a memory footprint.
|
||||||
type Domain = ChunkedBitSet<InitIndex>;
|
type Domain = ChunkedBitSet<InitIndex>;
|
||||||
@ -642,9 +635,7 @@ impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> {
|
|||||||
state.insert(InitIndex::new(arg_init));
|
state.insert(InitIndex::new(arg_init));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
|
|
||||||
#[instrument(skip(self, trans), level = "debug")]
|
#[instrument(skip(self, trans), level = "debug")]
|
||||||
fn apply_statement_effect(
|
fn apply_statement_effect(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -4,7 +4,7 @@ use rustc_middle::mir::{
|
|||||||
self, CallReturnPlaces, Local, Location, Place, StatementKind, TerminatorEdges,
|
self, CallReturnPlaces, Local, Location, Place, StatementKind, TerminatorEdges,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{Analysis, AnalysisDomain, Backward, GenKill};
|
use crate::{Analysis, Backward, GenKill};
|
||||||
|
|
||||||
/// A [live-variable dataflow analysis][liveness].
|
/// A [live-variable dataflow analysis][liveness].
|
||||||
///
|
///
|
||||||
@ -25,7 +25,7 @@ use crate::{Analysis, AnalysisDomain, Backward, GenKill};
|
|||||||
/// [liveness]: https://en.wikipedia.org/wiki/Live_variable_analysis
|
/// [liveness]: https://en.wikipedia.org/wiki/Live_variable_analysis
|
||||||
pub struct MaybeLiveLocals;
|
pub struct MaybeLiveLocals;
|
||||||
|
|
||||||
impl<'tcx> AnalysisDomain<'tcx> for MaybeLiveLocals {
|
impl<'tcx> Analysis<'tcx> for MaybeLiveLocals {
|
||||||
type Domain = BitSet<Local>;
|
type Domain = BitSet<Local>;
|
||||||
type Direction = Backward;
|
type Direction = Backward;
|
||||||
|
|
||||||
@ -39,9 +39,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeLiveLocals {
|
|||||||
fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) {
|
fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) {
|
||||||
// No variables are live until we observe a use
|
// No variables are live until we observe a use
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Analysis<'tcx> for MaybeLiveLocals {
|
|
||||||
fn apply_statement_effect(
|
fn apply_statement_effect(
|
||||||
&mut self,
|
&mut self,
|
||||||
trans: &mut Self::Domain,
|
trans: &mut Self::Domain,
|
||||||
@ -219,7 +217,7 @@ impl<'a> MaybeTransitiveLiveLocals<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeTransitiveLiveLocals<'a> {
|
impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
|
||||||
type Domain = BitSet<Local>;
|
type Domain = BitSet<Local>;
|
||||||
type Direction = Backward;
|
type Direction = Backward;
|
||||||
|
|
||||||
@ -233,9 +231,7 @@ impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeTransitiveLiveLocals<'a> {
|
|||||||
fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) {
|
fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) {
|
||||||
// No variables are live until we observe a use
|
// No variables are live until we observe a use
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
|
|
||||||
fn apply_statement_effect(
|
fn apply_statement_effect(
|
||||||
&mut self,
|
&mut self,
|
||||||
trans: &mut Self::Domain,
|
trans: &mut Self::Domain,
|
||||||
|
@ -5,7 +5,7 @@ use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
|
|||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
|
|
||||||
use super::MaybeBorrowedLocals;
|
use super::MaybeBorrowedLocals;
|
||||||
use crate::{Analysis, AnalysisDomain, GenKill, ResultsCursor};
|
use crate::{Analysis, GenKill, ResultsCursor};
|
||||||
|
|
||||||
pub struct MaybeStorageLive<'a> {
|
pub struct MaybeStorageLive<'a> {
|
||||||
always_live_locals: Cow<'a, BitSet<Local>>,
|
always_live_locals: Cow<'a, BitSet<Local>>,
|
||||||
@ -17,7 +17,7 @@ impl<'a> MaybeStorageLive<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeStorageLive<'a> {
|
impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageLive<'a> {
|
||||||
type Domain = BitSet<Local>;
|
type Domain = BitSet<Local>;
|
||||||
|
|
||||||
const NAME: &'static str = "maybe_storage_live";
|
const NAME: &'static str = "maybe_storage_live";
|
||||||
@ -37,9 +37,7 @@ impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeStorageLive<'a> {
|
|||||||
on_entry.insert(arg);
|
on_entry.insert(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageLive<'a> {
|
|
||||||
fn apply_statement_effect(
|
fn apply_statement_effect(
|
||||||
&mut self,
|
&mut self,
|
||||||
trans: &mut Self::Domain,
|
trans: &mut Self::Domain,
|
||||||
@ -83,7 +81,7 @@ impl<'a> MaybeStorageDead<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeStorageDead<'a> {
|
impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageDead<'a> {
|
||||||
type Domain = BitSet<Local>;
|
type Domain = BitSet<Local>;
|
||||||
|
|
||||||
const NAME: &'static str = "maybe_storage_dead";
|
const NAME: &'static str = "maybe_storage_dead";
|
||||||
@ -102,9 +100,7 @@ impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeStorageDead<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageDead<'a> {
|
|
||||||
fn apply_statement_effect(
|
fn apply_statement_effect(
|
||||||
&mut self,
|
&mut self,
|
||||||
trans: &mut Self::Domain,
|
trans: &mut Self::Domain,
|
||||||
@ -152,7 +148,7 @@ impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
|
impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
|
||||||
type Domain = BitSet<Local>;
|
type Domain = BitSet<Local>;
|
||||||
|
|
||||||
const NAME: &'static str = "requires_storage";
|
const NAME: &'static str = "requires_storage";
|
||||||
@ -169,9 +165,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
|
|||||||
on_entry.insert(arg);
|
on_entry.insert(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
|
|
||||||
fn apply_before_statement_effect(
|
fn apply_before_statement_effect(
|
||||||
&mut self,
|
&mut self,
|
||||||
trans: &mut Self::Domain,
|
trans: &mut Self::Domain,
|
||||||
@ -327,11 +321,7 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
|
|||||||
|
|
||||||
impl<'tcx> MaybeRequiresStorage<'_, 'tcx> {
|
impl<'tcx> MaybeRequiresStorage<'_, 'tcx> {
|
||||||
/// Kill locals that are fully moved and have not been borrowed.
|
/// Kill locals that are fully moved and have not been borrowed.
|
||||||
fn check_for_move(
|
fn check_for_move(&mut self, trans: &mut <Self as Analysis<'tcx>>::Domain, loc: Location) {
|
||||||
&mut self,
|
|
||||||
trans: &mut <Self as AnalysisDomain<'tcx>>::Domain,
|
|
||||||
loc: Location,
|
|
||||||
) {
|
|
||||||
let body = self.borrowed_locals.body();
|
let body = self.borrowed_locals.body();
|
||||||
let mut visitor = MoveVisitor { trans, borrowed_locals: &mut self.borrowed_locals };
|
let mut visitor = MoveVisitor { trans, borrowed_locals: &mut self.borrowed_locals };
|
||||||
visitor.visit_location(body, loc);
|
visitor.visit_location(body, loc);
|
||||||
|
@ -18,9 +18,9 @@ pub use self::drop_flag_effects::{
|
|||||||
move_path_children_matching, on_all_children_bits, on_lookup_result_bits,
|
move_path_children_matching, on_all_children_bits, on_lookup_result_bits,
|
||||||
};
|
};
|
||||||
pub use self::framework::{
|
pub use self::framework::{
|
||||||
Analysis, AnalysisDomain, Backward, Direction, Engine, Forward, GenKill, JoinSemiLattice,
|
Analysis, Backward, Direction, Engine, Forward, GenKill, JoinSemiLattice, MaybeReachable,
|
||||||
MaybeReachable, Results, ResultsCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects,
|
Results, ResultsCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz,
|
||||||
fmt, graphviz, lattice, visit_results,
|
lattice, visit_results,
|
||||||
};
|
};
|
||||||
use self::move_paths::MoveData;
|
use self::move_paths::MoveData;
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ use tracing::debug;
|
|||||||
|
|
||||||
use crate::fmt::DebugWithContext;
|
use crate::fmt::DebugWithContext;
|
||||||
use crate::lattice::{HasBottom, HasTop};
|
use crate::lattice::{HasBottom, HasTop};
|
||||||
use crate::{Analysis, AnalysisDomain, JoinSemiLattice, SwitchIntEdgeEffects};
|
use crate::{Analysis, JoinSemiLattice, SwitchIntEdgeEffects};
|
||||||
|
|
||||||
pub trait ValueAnalysis<'tcx> {
|
pub trait ValueAnalysis<'tcx> {
|
||||||
/// For each place of interest, the analysis tracks a value of the given type.
|
/// For each place of interest, the analysis tracks a value of the given type.
|
||||||
@ -334,7 +334,7 @@ pub trait ValueAnalysis<'tcx> {
|
|||||||
|
|
||||||
pub struct ValueAnalysisWrapper<T>(pub T);
|
pub struct ValueAnalysisWrapper<T>(pub T);
|
||||||
|
|
||||||
impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper<T> {
|
impl<'tcx, T: ValueAnalysis<'tcx>> Analysis<'tcx> for ValueAnalysisWrapper<T> {
|
||||||
type Domain = State<T::Value>;
|
type Domain = State<T::Value>;
|
||||||
|
|
||||||
const NAME: &'static str = T::NAME;
|
const NAME: &'static str = T::NAME;
|
||||||
@ -351,12 +351,7 @@ impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper
|
|||||||
state.flood(PlaceRef { local: arg, projection: &[] }, self.0.map());
|
state.flood(PlaceRef { local: arg, projection: &[] }, self.0.map());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx, T> Analysis<'tcx> for ValueAnalysisWrapper<T>
|
|
||||||
where
|
|
||||||
T: ValueAnalysis<'tcx>,
|
|
||||||
{
|
|
||||||
fn apply_statement_effect(
|
fn apply_statement_effect(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut Self::Domain,
|
state: &mut Self::Domain,
|
||||||
|
Loading…
Reference in New Issue
Block a user