diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-19 09:26:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-19 09:26:03 +0000 |
commit | 9918693037dce8aa4bb6f08741b6812923486c18 (patch) | |
tree | 21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /compiler/rustc_mir_dataflow | |
parent | Releasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff) | |
download | rustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip |
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_mir_dataflow')
20 files changed, 236 insertions, 476 deletions
diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml index 61664eb2a..7199db677 100644 --- a/compiler/rustc_mir_dataflow/Cargo.toml +++ b/compiler/rustc_mir_dataflow/Cargo.toml @@ -16,7 +16,6 @@ rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } -rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs index 163d74cc9..de1ca8d82 100644 --- a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs +++ b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs @@ -1,10 +1,8 @@ use crate::elaborate_drops::DropFlagState; use rustc_middle::mir::{self, Body, Location, Terminator, TerminatorKind}; -use rustc_middle::ty::TyCtxt; use rustc_target::abi::VariantIdx; -use super::indexes::MovePathIndex; -use super::move_paths::{InitKind, LookupResult, MoveData}; +use super::move_paths::{InitKind, LookupResult, MoveData, MovePathIndex}; use super::MoveDataParamEnv; pub fn move_path_children_matching<'tcx, F>( @@ -30,8 +28,6 @@ where } pub fn on_lookup_result_bits<'tcx, F>( - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, move_data: &MoveData<'tcx>, lookup_result: LookupResult, each_child: F, @@ -42,13 +38,11 @@ pub fn on_lookup_result_bits<'tcx, F>( LookupResult::Parent(..) => { // access to untracked value - do not touch children } - LookupResult::Exact(e) => on_all_children_bits(tcx, body, move_data, e, each_child), + LookupResult::Exact(e) => on_all_children_bits(move_data, e, each_child), } } pub fn on_all_children_bits<'tcx, F>( - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, move_data: &MoveData<'tcx>, move_path_index: MovePathIndex, mut each_child: F, @@ -56,8 +50,6 @@ pub fn on_all_children_bits<'tcx, F>( F: FnMut(MovePathIndex), { fn on_all_children_bits<'tcx, F>( - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, move_data: &MoveData<'tcx>, move_path_index: MovePathIndex, each_child: &mut F, @@ -68,15 +60,14 @@ pub fn on_all_children_bits<'tcx, F>( let mut next_child_index = move_data.move_paths[move_path_index].first_child; while let Some(child_index) = next_child_index { - on_all_children_bits(tcx, body, move_data, child_index, each_child); + on_all_children_bits(move_data, child_index, each_child); next_child_index = move_data.move_paths[child_index].next_sibling; } } - on_all_children_bits(tcx, body, move_data, move_path_index, &mut each_child); + on_all_children_bits(move_data, move_path_index, &mut each_child); } pub fn drop_flag_effects_for_function_entry<'tcx, F>( - tcx: TyCtxt<'tcx>, body: &Body<'tcx>, ctxt: &MoveDataParamEnv<'tcx>, mut callback: F, @@ -87,14 +78,13 @@ pub fn drop_flag_effects_for_function_entry<'tcx, F>( for arg in body.args_iter() { let place = mir::Place::from(arg); let lookup_result = move_data.rev_lookup.find(place.as_ref()); - on_lookup_result_bits(tcx, body, move_data, lookup_result, |mpi| { + on_lookup_result_bits(move_data, lookup_result, |mpi| { callback(mpi, DropFlagState::Present) }); } } pub fn drop_flag_effects_for_location<'tcx, F>( - tcx: TyCtxt<'tcx>, body: &Body<'tcx>, ctxt: &MoveDataParamEnv<'tcx>, loc: Location, @@ -110,7 +100,7 @@ pub fn drop_flag_effects_for_location<'tcx, F>( let path = mi.move_path_index(move_data); debug!("moving out of path {:?}", move_data.move_paths[path]); - on_all_children_bits(tcx, body, move_data, path, |mpi| callback(mpi, DropFlagState::Absent)) + on_all_children_bits(move_data, path, |mpi| callback(mpi, DropFlagState::Absent)) } // Drop does not count as a move but we should still consider the variable uninitialized. @@ -118,24 +108,17 @@ pub fn drop_flag_effects_for_location<'tcx, F>( body.stmt_at(loc).right() { if let LookupResult::Exact(mpi) = move_data.rev_lookup.find(place.as_ref()) { - on_all_children_bits(tcx, body, move_data, mpi, |mpi| { - callback(mpi, DropFlagState::Absent) - }) + on_all_children_bits(move_data, mpi, |mpi| callback(mpi, DropFlagState::Absent)) } } debug!("drop_flag_effects: assignment for location({:?})", loc); - for_location_inits(tcx, body, move_data, loc, |mpi| callback(mpi, DropFlagState::Present)); + for_location_inits(move_data, loc, |mpi| callback(mpi, DropFlagState::Present)); } -pub fn for_location_inits<'tcx, F>( - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, - move_data: &MoveData<'tcx>, - loc: Location, - mut callback: F, -) where +fn for_location_inits<'tcx, F>(move_data: &MoveData<'tcx>, loc: Location, mut callback: F) +where F: FnMut(MovePathIndex), { for ii in &move_data.init_loc_map[loc] { @@ -144,7 +127,7 @@ pub fn for_location_inits<'tcx, F>( InitKind::Deep => { let path = init.path; - on_all_children_bits(tcx, body, move_data, path, &mut callback) + on_all_children_bits(move_data, path, &mut callback) } InitKind::Shallow => { let mpi = init.path; @@ -161,8 +144,6 @@ pub fn for_location_inits<'tcx, F>( /// NOTE: If there are no move paths corresponding to an inactive variant, /// `handle_inactive_variant` will not be called for that variant. pub(crate) fn on_all_inactive_variants<'tcx>( - tcx: TyCtxt<'tcx>, - body: &mir::Body<'tcx>, move_data: &MoveData<'tcx>, enum_place: mir::Place<'tcx>, active_variant: VariantIdx, @@ -185,9 +166,7 @@ pub(crate) fn on_all_inactive_variants<'tcx>( }; if variant_idx != active_variant { - on_all_children_bits(tcx, body, move_data, variant_mpi, |mpi| { - handle_inactive_variant(mpi) - }); + on_all_children_bits(move_data, variant_mpi, |mpi| handle_inactive_variant(mpi)); } } } diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 25ba67a63..958fa0d17 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -481,12 +481,8 @@ where ) -> (BasicBlock, Unwind) { let (succ, unwind) = self.drop_ladder_bottom(); if !adt.is_enum() { - let fields = self.move_paths_for_fields( - self.place, - self.path, - &adt.variant(FIRST_VARIANT), - args, - ); + let fields = + self.move_paths_for_fields(self.place, self.path, adt.variant(FIRST_VARIANT), args); self.drop_ladder(fields, succ, unwind) } else { self.open_drop_for_multivariant(adt, args, succ, unwind) @@ -518,7 +514,7 @@ where self.place, ProjectionElem::Downcast(Some(variant.name), variant_index), ); - let fields = self.move_paths_for_fields(base_place, variant_path, &variant, args); + let fields = self.move_paths_for_fields(base_place, variant_path, variant, args); values.push(discr.val); if let Unwind::To(unwind) = unwind { // We can't use the half-ladder from the original @@ -859,14 +855,14 @@ where fn open_drop(&mut self) -> BasicBlock { let ty = self.place_ty(self.place); match ty.kind() { - ty::Closure(_, args) => self.open_drop_for_tuple(&args.as_closure().upvar_tys()), + ty::Closure(_, args) => self.open_drop_for_tuple(args.as_closure().upvar_tys()), // Note that `elaborate_drops` only drops the upvars of a coroutine, // and this is ok because `open_drop` here can only be reached // within that own coroutine's resume function. // This should only happen for the self argument on the resume function. // It effectively only contains upvars until the coroutine transformation runs. // See librustc_body/transform/coroutine.rs for more details. - ty::Coroutine(_, args, _) => self.open_drop_for_tuple(&args.as_coroutine().upvar_tys()), + ty::Coroutine(_, args, _) => self.open_drop_for_tuple(args.as_coroutine().upvar_tys()), ty::Tuple(fields) => self.open_drop_for_tuple(fields), ty::Adt(def, args) => self.open_drop_for_adt(*def, args), ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind), diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs index c978bddfe..815f20459 100644 --- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs @@ -1,60 +1,14 @@ //! Random access inspection of the results of a dataflow analysis. -use crate::{framework::BitSetExt, CloneAnalysis}; +use crate::framework::BitSetExt; -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, 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<'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>>; +use super::{Analysis, Direction, Effect, EffectIndex, Results}; /// Allows random access inspection of the results of a dataflow analysis. /// @@ -62,15 +16,12 @@ pub type ResultsClonedCursor<'res, 'mir, 'tcx, A> = /// the same order as the `DIRECTION` of the analysis. In the worst case—when statements are /// visited in *reverse* order—performance will be quadratic in the number of statements in the /// block. The order in which basic blocks are inspected has no impact on performance. -/// -/// A `ResultsCursor` can either own (the default) or borrow the dataflow results it inspects. The -/// type of ownership is determined by `R` (see `ResultsRefCursor` above). -pub struct ResultsCursor<'mir, 'tcx, A, R = Results<'tcx, A>> +pub struct ResultsCursor<'mir, 'tcx, A> where A: Analysis<'tcx>, { body: &'mir mir::Body<'tcx>, - results: R, + results: Results<'tcx, A>, state: A::Domain, pos: CursorPosition, @@ -84,7 +35,7 @@ where reachable_blocks: BitSet<BasicBlock>, } -impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R> +impl<'mir, 'tcx, A> ResultsCursor<'mir, 'tcx, A> where A: Analysis<'tcx>, { @@ -99,30 +50,13 @@ where } /// Unwraps this cursor, returning the underlying `Results`. - pub fn into_results(self) -> R { + pub fn into_results(self) -> Results<'tcx, A> { 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 { - let bottom_value = results.borrow().analysis.bottom_value(body); + pub fn new(body: &'mir mir::Body<'tcx>, results: Results<'tcx, A>) -> Self { + let bottom_value = results.analysis.bottom_value(body); ResultsCursor { body, results, @@ -147,28 +81,23 @@ where } /// Returns the underlying `Results`. - pub fn results(&mut self) -> &Results<'tcx, A, R::EntrySets> { - self.results.borrow() + pub fn results(&self) -> &Results<'tcx, A> { + &self.results } /// Returns the underlying `Results`. - pub fn mut_results(&mut self) -> &mut Results<'tcx, A, R::EntrySets> { - self.results.borrow_mut() + pub fn mut_results(&mut self) -> &mut Results<'tcx, A> { + &mut self.results } /// Returns the `Analysis` used to generate the underlying `Results`. pub fn analysis(&self) -> &A { - &self.results.borrow().analysis + &self.results.analysis } /// 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) + &mut self.results.analysis } /// Resets the cursor to hold the entry set for the given basic block. @@ -180,7 +109,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.entry_set_for_block(block)); self.pos = CursorPosition::block_entry(block); self.state_needs_reset = false; } @@ -269,11 +198,10 @@ where ) }; - let analysis = &mut self.results.borrow_mut().analysis; let target_effect_index = effect.at_index(target.statement_index); A::Direction::apply_effects_in_range( - analysis, + &mut self.results.analysis, &mut self.state, target.block, block_data, @@ -289,12 +217,12 @@ 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(&mut A, &mut A::Domain)) { - f(&mut self.results.borrow_mut().analysis, &mut self.state); + f(&mut self.results.analysis, &mut self.state); self.state_needs_reset = true; } } -impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R> +impl<'mir, 'tcx, A> ResultsCursor<'mir, 'tcx, A> where A: crate::GenKillAnalysis<'tcx>, A::Domain: BitSetExt<A::Idx>, diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 70451edd5..4c3fadf48 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -196,7 +196,7 @@ impl Direction for Backward { { results.reset_to_block_entry(state, block); - vis.visit_block_end(results, &state, block_data, block); + vis.visit_block_end(state); // Terminator let loc = Location { block, statement_index: block_data.statements.len() }; @@ -214,7 +214,7 @@ impl Direction for Backward { vis.visit_statement_after_primary_effect(results, state, stmt, loc); } - vis.visit_block_start(results, state, block_data, block); + vis.visit_block_start(state); } fn join_state_into_successors_of<'tcx, A>( @@ -287,12 +287,12 @@ impl Direction for Backward { } } -struct BackwardSwitchIntEdgeEffectsApplier<'a, 'tcx, D, F> { - body: &'a mir::Body<'tcx>, +struct BackwardSwitchIntEdgeEffectsApplier<'mir, 'tcx, D, F> { + body: &'mir mir::Body<'tcx>, pred: BasicBlock, - exit_state: &'a mut D, + exit_state: &'mir mut D, bb: BasicBlock, - propagate: &'a mut F, + propagate: &'mir mut F, effects_applied: bool, } @@ -449,7 +449,7 @@ impl Direction for Forward { { results.reset_to_block_entry(state, block); - vis.visit_block_start(results, state, block_data, block); + vis.visit_block_start(state); for (statement_index, stmt) in block_data.statements.iter().enumerate() { let loc = Location { block, statement_index }; @@ -466,7 +466,7 @@ impl Direction for Forward { results.reconstruct_terminator_effect(state, term, loc); vis.visit_terminator_after_primary_effect(results, state, term, loc); - vis.visit_block_end(results, state, block_data, block); + vis.visit_block_end(state); } fn join_state_into_successors_of<'tcx, A>( @@ -523,9 +523,9 @@ impl Direction for Forward { } } -struct ForwardSwitchIntEdgeEffectsApplier<'a, D, F> { - exit_state: &'a mut D, - targets: &'a SwitchTargets, +struct ForwardSwitchIntEdgeEffectsApplier<'mir, D, F> { + exit_state: &'mir mut D, + targets: &'mir SwitchTargets, propagate: F, effects_applied: bool, diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index a29962d77..784872c7e 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -5,9 +5,7 @@ use crate::errors::{ }; use crate::framework::BitSetExt; -use std::borrow::Borrow; use std::ffi::OsString; -use std::marker::PhantomData; use std::path::PathBuf; use rustc_ast as ast; @@ -24,42 +22,37 @@ use rustc_span::symbol::{sym, Symbol}; use super::fmt::DebugWithContext; use super::graphviz; use super::{ - visit_results, Analysis, AnalysisDomain, CloneAnalysis, Direction, GenKill, GenKillAnalysis, - GenKillSet, JoinSemiLattice, ResultsClonedCursor, ResultsCursor, ResultsRefCursor, - ResultsVisitor, + visit_results, Analysis, AnalysisDomain, Direction, GenKill, GenKillAnalysis, GenKillSet, + JoinSemiLattice, ResultsCursor, ResultsVisitor, }; pub type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as AnalysisDomain<'tcx>>::Domain>; /// A dataflow analysis that has converged to fixpoint. -pub struct Results<'tcx, A, E = EntrySets<'tcx, A>> +#[derive(Clone)] +pub struct Results<'tcx, A> where A: Analysis<'tcx>, { pub analysis: A, - pub(super) entry_sets: E, - pub(super) _marker: PhantomData<&'tcx ()>, + pub(super) entry_sets: EntrySets<'tcx, A>, } -/// `Results` type with a cloned `Analysis` and borrowed entry sets. -pub type ResultsCloned<'res, 'tcx, A> = Results<'tcx, A, &'res EntrySets<'tcx, A>>; - -impl<'tcx, A, E> Results<'tcx, A, E> +impl<'tcx, A> Results<'tcx, A> where A: Analysis<'tcx>, - E: Borrow<EntrySets<'tcx, A>>, { /// Creates a `ResultsCursor` that can inspect these `Results`. pub fn into_results_cursor<'mir>( self, body: &'mir mir::Body<'tcx>, - ) -> ResultsCursor<'mir, 'tcx, A, Self> { + ) -> ResultsCursor<'mir, 'tcx, A> { ResultsCursor::new(body, self) } /// Gets the dataflow state for the given block. pub fn entry_set_for_block(&self, block: BasicBlock) -> &A::Domain { - &self.entry_sets.borrow()[block] + &self.entry_sets[block] } pub fn visit_with<'mir>( @@ -80,60 +73,14 @@ where visit_results(body, blocks.map(|(bb, _)| bb), self, vis) } } -impl<'tcx, A> Results<'tcx, A> -where - A: Analysis<'tcx>, -{ - /// Creates a `ResultsCursor` that can inspect these `Results`. - pub fn as_results_cursor<'a, 'mir>( - &'a mut self, - body: &'mir mir::Body<'tcx>, - ) -> ResultsRefCursor<'a, 'mir, 'tcx, A> { - ResultsCursor::new(body, self) - } -} -impl<'tcx, A> Results<'tcx, A> -where - A: Analysis<'tcx> + CloneAnalysis, -{ - /// Creates a new `Results` type with a cloned `Analysis` and borrowed entry sets. - pub fn clone_analysis(&self) -> ResultsCloned<'_, 'tcx, A> { - Results { - analysis: self.analysis.clone_analysis(), - entry_sets: &self.entry_sets, - _marker: PhantomData, - } - } - - /// Creates a `ResultsCursor` that can inspect these `Results`. - pub fn cloned_results_cursor<'mir>( - &self, - body: &'mir mir::Body<'tcx>, - ) -> ResultsClonedCursor<'_, 'mir, 'tcx, A> { - self.clone_analysis().into_results_cursor(body) - } -} -impl<'res, 'tcx, A> Results<'tcx, A, &'res EntrySets<'tcx, A>> -where - A: Analysis<'tcx> + CloneAnalysis, -{ - /// Creates a new `Results` type with a cloned `Analysis` and borrowed entry sets. - pub fn reclone_analysis(&self) -> Self { - Results { - analysis: self.analysis.clone_analysis(), - entry_sets: self.entry_sets, - _marker: PhantomData, - } - } -} /// A solver for dataflow problems. -pub struct Engine<'a, 'tcx, A> +pub struct Engine<'mir, 'tcx, A> where A: Analysis<'tcx>, { tcx: TyCtxt<'tcx>, - body: &'a mir::Body<'tcx>, + body: &'mir mir::Body<'tcx>, entry_sets: IndexVec<BasicBlock, A::Domain>, pass_name: Option<&'static str>, analysis: A, @@ -147,14 +94,14 @@ where apply_statement_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>, } -impl<'a, 'tcx, A, D, T> Engine<'a, 'tcx, A> +impl<'mir, 'tcx, A, D, T> Engine<'mir, 'tcx, A> where A: GenKillAnalysis<'tcx, Idx = T, Domain = D>, D: Clone + JoinSemiLattice + GenKill<T> + BitSetExt<T>, T: Idx, { /// Creates a new `Engine` to solve a gen-kill dataflow problem. - pub fn new_gen_kill(tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>, mut analysis: A) -> Self { + pub fn new_gen_kill(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, mut analysis: A) -> Self { // If there are no back-edges in the control-flow graph, we only ever need to apply the // transfer function for each block exactly once (assuming that we process blocks in RPO). // @@ -186,7 +133,7 @@ where } } -impl<'a, 'tcx, A, D> Engine<'a, 'tcx, A> +impl<'mir, 'tcx, A, D> Engine<'mir, 'tcx, A> where A: Analysis<'tcx, Domain = D>, D: Clone + JoinSemiLattice, @@ -196,13 +143,13 @@ where /// /// Gen-kill problems should use `new_gen_kill`, which will coalesce transfer functions for /// better performance. - pub fn new_generic(tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>, analysis: A) -> Self { + pub fn new_generic(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, analysis: A) -> Self { Self::new(tcx, body, analysis, None) } fn new( tcx: TyCtxt<'tcx>, - body: &'a mir::Body<'tcx>, + body: &'mir mir::Body<'tcx>, analysis: A, apply_statement_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>, ) -> Self { @@ -239,7 +186,6 @@ where tcx, apply_statement_trans_for_block, pass_name, - .. } = self; let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks.len()); @@ -292,29 +238,31 @@ where ); } - let mut results = Results { analysis, entry_sets, _marker: PhantomData }; + let results = Results { analysis, entry_sets }; if tcx.sess.opts.unstable_opts.dump_mir_dataflow { - let res = write_graphviz_results(tcx, &body, &mut results, pass_name); + let (res, results) = write_graphviz_results(tcx, body, results, pass_name); if let Err(e) = res { error!("Failed to write graphviz dataflow results: {}", e); } + results + } else { + results } - - results } } // Graphviz /// Writes a DOT file containing the results of a dataflow analysis if the user requested it via -/// `rustc_mir` attributes and `-Z dump-mir-dataflow`. +/// `rustc_mir` attributes and `-Z dump-mir-dataflow`. The `Result` in and the `Results` out are +/// the same. fn write_graphviz_results<'tcx, A>( tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>, - results: &mut Results<'tcx, A>, + results: Results<'tcx, A>, pass_name: Option<&'static str>, -) -> std::io::Result<()> +) -> (std::io::Result<()>, Results<'tcx, A>) where A: Analysis<'tcx>, A::Domain: DebugWithContext<A>, @@ -325,23 +273,30 @@ where let def_id = body.source.def_id(); let Ok(attrs) = RustcMirAttrs::parse(tcx, def_id) else { // Invalid `rustc_mir` attrs are reported in `RustcMirAttrs::parse` - return Ok(()); + return (Ok(()), results); }; - let mut file = match attrs.output_path(A::NAME) { - Some(path) => { - debug!("printing dataflow results for {:?} to {}", def_id, path.display()); - if let Some(parent) = path.parent() { - fs::create_dir_all(parent)?; + let file = try { + match attrs.output_path(A::NAME) { + Some(path) => { + debug!("printing dataflow results for {:?} to {}", def_id, path.display()); + if let Some(parent) = path.parent() { + fs::create_dir_all(parent)?; + } + let f = fs::File::create(&path)?; + io::BufWriter::new(f) } - io::BufWriter::new(fs::File::create(&path)?) - } - None if dump_enabled(tcx, A::NAME, def_id) => { - create_dump_file(tcx, ".dot", false, A::NAME, &pass_name.unwrap_or("-----"), body)? - } + None if dump_enabled(tcx, A::NAME, def_id) => { + create_dump_file(tcx, ".dot", false, A::NAME, &pass_name.unwrap_or("-----"), body)? + } - _ => return Ok(()), + _ => return (Ok(()), results), + } + }; + let mut file = match file { + Ok(f) => f, + Err(e) => return (Err(e), results), }; let style = match attrs.formatter { @@ -357,11 +312,14 @@ where if tcx.sess.opts.unstable_opts.graphviz_dark_mode { render_opts.push(dot::RenderOption::DarkTheme); } - with_no_trimmed_paths!(dot::render_opts(&graphviz, &mut buf, &render_opts)?); + let r = with_no_trimmed_paths!(dot::render_opts(&graphviz, &mut buf, &render_opts)); - file.write_all(&buf)?; + let lhs = try { + r?; + file.write_all(&buf)?; + }; - Ok(()) + (lhs, graphviz.into_results()) } #[derive(Default)] diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index c12ccba1e..0270e059a 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -12,10 +12,10 @@ use rustc_middle::mir::graphviz_safe_def_name; use rustc_middle::mir::{self, BasicBlock, Body, Location}; use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext}; -use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsRefCursor, ResultsVisitor}; +use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsCursor, ResultsVisitor}; #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum OutputStyle { +pub(crate) enum OutputStyle { AfterOnly, BeforeAndAfter, } @@ -29,33 +29,37 @@ impl OutputStyle { } } -pub struct Formatter<'res, 'mir, 'tcx, A> +pub(crate) struct Formatter<'mir, 'tcx, A> where A: Analysis<'tcx>, { body: &'mir Body<'tcx>, - results: RefCell<&'res mut Results<'tcx, A>>, + results: RefCell<Option<Results<'tcx, A>>>, style: OutputStyle, reachable: BitSet<BasicBlock>, } -impl<'res, 'mir, 'tcx, A> Formatter<'res, 'mir, 'tcx, A> +impl<'mir, 'tcx, A> Formatter<'mir, 'tcx, A> where A: Analysis<'tcx>, { - pub fn new( + pub(crate) fn new( body: &'mir Body<'tcx>, - results: &'res mut Results<'tcx, A>, + results: Results<'tcx, A>, style: OutputStyle, ) -> Self { let reachable = mir::traversal::reachable_as_bitset(body); - Formatter { body, results: results.into(), style, reachable } + Formatter { body, results: Some(results).into(), style, reachable } + } + + pub(crate) fn into_results(self) -> Results<'tcx, A> { + self.results.into_inner().unwrap() } } /// A pair of a basic block and an index into that basic blocks `successors`. #[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct CfgEdge { +pub(crate) struct CfgEdge { source: BasicBlock, index: usize, } @@ -69,7 +73,7 @@ fn dataflow_successors(body: &Body<'_>, bb: BasicBlock) -> Vec<CfgEdge> { .collect() } -impl<'tcx, A> dot::Labeller<'_> for Formatter<'_, '_, 'tcx, A> +impl<'tcx, A> dot::Labeller<'_> for Formatter<'_, 'tcx, A> where A: Analysis<'tcx>, A::Domain: DebugWithContext<A>, @@ -88,14 +92,19 @@ where fn node_label(&self, block: &Self::Node) -> dot::LabelText<'_> { let mut label = Vec::new(); - let mut results = self.results.borrow_mut(); - let mut fmt = BlockFormatter { - results: results.as_results_cursor(self.body), - style: self.style, - bg: Background::Light, - }; + self.results.replace_with(|results| { + // `Formatter::result` is a `RefCell<Option<_>>` so we can replace + // the value with `None`, move it into the results cursor, move it + // back out, and return it to the refcell wrapped in `Some`. + let mut fmt = BlockFormatter { + results: results.take().unwrap().into_results_cursor(self.body), + style: self.style, + bg: Background::Light, + }; - fmt.write_node_label(&mut label, *block).unwrap(); + fmt.write_node_label(&mut label, *block).unwrap(); + Some(fmt.results.into_results()) + }); dot::LabelText::html(String::from_utf8(label).unwrap()) } @@ -109,7 +118,7 @@ where } } -impl<'mir, 'tcx, A> dot::GraphWalk<'mir> for Formatter<'_, 'mir, 'tcx, A> +impl<'mir, 'tcx, A> dot::GraphWalk<'mir> for Formatter<'mir, 'tcx, A> where A: Analysis<'tcx>, { @@ -143,16 +152,16 @@ where } } -struct BlockFormatter<'res, 'mir, 'tcx, A> +struct BlockFormatter<'mir, 'tcx, A> where A: Analysis<'tcx>, { - results: ResultsRefCursor<'res, 'mir, 'tcx, A>, + results: ResultsCursor<'mir, 'tcx, A>, bg: Background, style: OutputStyle, } -impl<'res, 'mir, 'tcx, A> BlockFormatter<'res, 'mir, 'tcx, A> +impl<'mir, 'tcx, A> BlockFormatter<'mir, 'tcx, A> where A: Analysis<'tcx>, A::Domain: DebugWithContext<A>, @@ -536,25 +545,13 @@ where { type FlowState = A::Domain; - fn visit_block_start( - &mut self, - _results: &mut Results<'tcx, A>, - state: &Self::FlowState, - _block_data: &mir::BasicBlockData<'tcx>, - _block: BasicBlock, - ) { + fn visit_block_start(&mut self, state: &Self::FlowState) { if A::Direction::IS_FORWARD { self.prev_state.clone_from(state); } } - fn visit_block_end( - &mut self, - _results: &mut Results<'tcx, A>, - state: &Self::FlowState, - _block_data: &mir::BasicBlockData<'tcx>, - _block: BasicBlock, - ) { + fn visit_block_end(&mut self, state: &Self::FlowState) { if A::Direction::IS_BACKWARD { self.prev_state.clone_from(state); } diff --git a/compiler/rustc_mir_dataflow/src/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs index 3b89598d2..1c2b475a4 100644 --- a/compiler/rustc_mir_dataflow/src/framework/lattice.rs +++ b/compiler/rustc_mir_dataflow/src/framework/lattice.rs @@ -342,7 +342,7 @@ impl<V: Clone> Clone for MaybeReachable<V> { fn clone_from(&mut self, source: &Self) { match (&mut *self, source) { (MaybeReachable::Reachable(x), MaybeReachable::Reachable(y)) => { - x.clone_from(&y); + x.clone_from(y); } _ => *self = source.clone(), } diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 5020a1cf0..09cdb055a 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -45,9 +45,9 @@ pub mod graphviz; pub mod lattice; mod visitor; -pub use self::cursor::{AnalysisResults, ResultsClonedCursor, ResultsCursor, ResultsRefCursor}; +pub use self::cursor::ResultsCursor; pub use self::direction::{Backward, Direction, Forward}; -pub use self::engine::{Engine, EntrySets, Results, ResultsCloned}; +pub use self::engine::{Engine, Results}; pub use self::lattice::{JoinSemiLattice, MaybeReachable}; pub use self::visitor::{visit_results, ResultsVisitable, ResultsVisitor}; @@ -246,35 +246,21 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { } } -/// Defines an `Analysis` which can be cloned for use in multiple `ResultsCursor`s or -/// `ResultsVisitor`s. Note this need not be a full clone, only enough of one to be used with a new -/// `ResultsCursor` or `ResultsVisitor` -pub trait CloneAnalysis { - fn clone_analysis(&self) -> Self; -} -impl<'tcx, A> CloneAnalysis for A -where - A: Analysis<'tcx> + Copy, -{ - fn clone_analysis(&self) -> Self { - *self - } -} - /// A gen/kill dataflow problem. /// -/// Each method in this trait has a corresponding one in `Analysis`. However, these methods only -/// allow modification of the dataflow state via "gen" and "kill" operations. By defining transfer -/// functions for each statement in this way, the transfer function for an entire basic block can -/// be computed efficiently. +/// Each method in this trait has a corresponding one in `Analysis`. However, the first two methods +/// here only allow modification of the dataflow state via "gen" and "kill" operations. By defining +/// transfer functions for each statement in this way, the transfer function for an entire basic +/// block can be computed efficiently. The remaining methods match up with `Analysis` exactly. /// -/// `Analysis` is automatically implemented for all implementers of `GenKillAnalysis`. +/// `Analysis` is automatically implemented for all implementers of `GenKillAnalysis` via a blanket +/// impl below. pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> { type Idx: Idx; fn domain_size(&self, body: &mir::Body<'tcx>) -> usize; - /// See `Analysis::apply_statement_effect`. + /// See `Analysis::apply_statement_effect`. Note how the second arg differs. fn statement_effect( &mut self, trans: &mut impl GenKill<Self::Idx>, @@ -282,7 +268,8 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> { location: Location, ); - /// See `Analysis::apply_before_statement_effect`. + /// See `Analysis::apply_before_statement_effect`. Note how the second arg + /// differs. fn before_statement_effect( &mut self, _trans: &mut impl GenKill<Self::Idx>, @@ -302,7 +289,7 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> { /// See `Analysis::apply_before_terminator_effect`. fn before_terminator_effect( &mut self, - _trans: &mut impl GenKill<Self::Idx>, + _trans: &mut Self::Domain, _terminator: &mir::Terminator<'tcx>, _location: Location, ) { @@ -313,7 +300,7 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> { /// See `Analysis::apply_call_return_effect`. fn call_return_effect( &mut self, - trans: &mut impl GenKill<Self::Idx>, + trans: &mut Self::Domain, block: BasicBlock, return_places: CallReturnPlaces<'_, 'tcx>, ); @@ -328,6 +315,7 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> { } } +// Blanket impl: any impl of `GenKillAnalysis` automatically impls `Analysis`. impl<'tcx, A> Analysis<'tcx> for A where A: GenKillAnalysis<'tcx>, diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs index 9cce5b26c..6b338efd5 100644 --- a/compiler/rustc_mir_dataflow/src/framework/tests.rs +++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs @@ -2,9 +2,7 @@ use std::marker::PhantomData; -use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; -use rustc_middle::mir::{self, BasicBlock, Location}; use rustc_middle::ty; use rustc_span::DUMMY_SP; @@ -267,8 +265,7 @@ fn test_cursor<D: Direction>(analysis: MockAnalysis<'_, D>) { let body = analysis.body; let mut cursor = - Results { entry_sets: analysis.mock_entry_sets(), analysis, _marker: PhantomData } - .into_results_cursor(body); + Results { entry_sets: analysis.mock_entry_sets(), analysis }.into_results_cursor(body); cursor.allow_unreachable(); diff --git a/compiler/rustc_mir_dataflow/src/framework/visitor.rs b/compiler/rustc_mir_dataflow/src/framework/visitor.rs index 3cfa7cc1c..8b8a16bda 100644 --- a/compiler/rustc_mir_dataflow/src/framework/visitor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/visitor.rs @@ -1,8 +1,6 @@ -use std::borrow::Borrow; - use rustc_middle::mir::{self, BasicBlock, Location}; -use super::{Analysis, Direction, EntrySets, Results}; +use super::{Analysis, Direction, Results}; /// Calls the corresponding method in `ResultsVisitor` for every location in a `mir::Body` with the /// dataflow state at that location. @@ -33,14 +31,7 @@ pub fn visit_results<'mir, 'tcx, F, R>( pub trait ResultsVisitor<'mir, 'tcx, R> { type FlowState; - fn visit_block_start( - &mut self, - _results: &mut R, - _state: &Self::FlowState, - _block_data: &'mir mir::BasicBlockData<'tcx>, - _block: BasicBlock, - ) { - } + fn visit_block_start(&mut self, _state: &Self::FlowState) {} /// Called with the `before_statement_effect` of the given statement applied to `state` but not /// its `statement_effect`. @@ -88,20 +79,13 @@ pub trait ResultsVisitor<'mir, 'tcx, R> { ) { } - fn visit_block_end( - &mut self, - _results: &mut R, - _state: &Self::FlowState, - _block_data: &'mir mir::BasicBlockData<'tcx>, - _block: BasicBlock, - ) { - } + fn visit_block_end(&mut self, _state: &Self::FlowState) {} } /// Things that can be visited by a `ResultsVisitor`. /// -/// This trait exists so that we can visit the results of multiple dataflow analyses simultaneously. -/// DO NOT IMPLEMENT MANUALLY. Instead, use the `impl_visitable` macro below. +/// This trait exists so that we can visit the results of one or more dataflow analyses +/// simultaneously. pub trait ResultsVisitable<'tcx> { type Direction: Direction; type FlowState; @@ -143,10 +127,9 @@ pub trait ResultsVisitable<'tcx> { ); } -impl<'tcx, A, E> ResultsVisitable<'tcx> for Results<'tcx, A, E> +impl<'tcx, A> ResultsVisitable<'tcx> for Results<'tcx, A> where A: Analysis<'tcx>, - E: Borrow<EntrySets<'tcx, A>>, { type FlowState = A::Domain; diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 01acc380f..693994b5d 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -62,7 +62,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeBorrowedLocals { fn call_return_effect( &mut self, - _trans: &mut impl GenKill<Self::Idx>, + _trans: &mut Self::Domain, _block: BasicBlock, _return_places: CallReturnPlaces<'_, 'tcx>, ) { diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index c968e7aea..6653b99b3 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -72,7 +72,7 @@ impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { ) -> bool { if let LookupResult::Exact(path) = self.move_data().rev_lookup.find(place.as_ref()) { let mut maybe_live = false; - on_all_children_bits(self.tcx, self.body, self.move_data(), path, |child| { + on_all_children_bits(self.move_data(), path, |child| { maybe_live |= state.contains(child); }); !maybe_live @@ -203,14 +203,13 @@ impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, 'tcx> { /// this data and `MaybeInitializedPlaces` yields the set of places /// that would require a dynamic drop-flag at that statement. pub struct DefinitelyInitializedPlaces<'a, 'tcx> { - tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>, } impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { - DefinitelyInitializedPlaces { tcx, body, mdpe } + pub fn new(body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { + DefinitelyInitializedPlaces { body, mdpe } } } @@ -250,15 +249,13 @@ impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> { /// } /// ``` pub struct EverInitializedPlaces<'a, 'tcx> { - #[allow(dead_code)] - tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>, } impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { - EverInitializedPlaces { tcx, body, mdpe } + pub fn new(body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { + EverInitializedPlaces { body, mdpe } } } @@ -319,7 +316,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) { *state = MaybeReachable::Reachable(ChunkedBitSet::new_empty(self.move_data().move_paths.len())); - drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| { + drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| { assert!(s == DropFlagState::Present); state.gen(path); }); @@ -339,7 +336,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { statement: &mir::Statement<'tcx>, location: Location, ) { - drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { Self::update_bits(trans, path, s) }); @@ -351,7 +348,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { | mir::Rvalue::AddressOf(_, place) = rvalue && let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) { - on_all_children_bits(self.tcx, self.body, self.move_data(), mpi, |child| { + on_all_children_bits(self.move_data(), mpi, |child| { trans.gen(child); }) } @@ -371,7 +368,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { { edges = TerminatorEdges::Single(target); } - drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { Self::update_bits(state, path, s) }); edges @@ -379,7 +376,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { fn call_return_effect( &mut self, - trans: &mut impl GenKill<Self::Idx>, + trans: &mut Self::Domain, _block: mir::BasicBlock, return_places: CallReturnPlaces<'_, 'tcx>, ) { @@ -387,8 +384,6 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { // when a call returns successfully, that means we need to set // the bits for that dest_place to 1 (initialized). on_lookup_result_bits( - self.tcx, - self.body, self.move_data(), self.move_data().rev_lookup.find(place.as_ref()), |mpi| { @@ -409,7 +404,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { } let enum_ = discr.place().and_then(|discr| { - switch_on_enum_discriminant(self.tcx, &self.body, &self.body[block], discr) + switch_on_enum_discriminant(self.tcx, self.body, &self.body[block], discr) }); let Some((enum_place, enum_def)) = enum_ else { @@ -432,8 +427,6 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { // Kill all move paths that correspond to variants we know to be inactive along this // particular outgoing edge of a `SwitchInt`. drop_flag_effects::on_all_inactive_variants( - self.tcx, - self.body, self.move_data(), enum_place, variant, @@ -458,7 +451,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { // set all bits to 1 (uninit) before gathering counter-evidence state.insert_all(); - drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| { + drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| { assert!(s == DropFlagState::Present); state.remove(path); }); @@ -478,7 +471,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { _statement: &mir::Statement<'tcx>, location: Location, ) { - drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { Self::update_bits(trans, path, s) }); @@ -492,7 +485,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { terminator: &'mir mir::Terminator<'tcx>, location: Location, ) -> TerminatorEdges<'mir, 'tcx> { - drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { Self::update_bits(trans, path, s) }); if self.skip_unreachable_unwind.contains(location.block) { @@ -506,7 +499,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { fn call_return_effect( &mut self, - trans: &mut impl GenKill<Self::Idx>, + trans: &mut Self::Domain, _block: mir::BasicBlock, return_places: CallReturnPlaces<'_, 'tcx>, ) { @@ -514,8 +507,6 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { // when a call returns successfully, that means we need to set // the bits for that dest_place to 0 (initialized). on_lookup_result_bits( - self.tcx, - self.body, self.move_data(), self.move_data().rev_lookup.find(place.as_ref()), |mpi| { @@ -540,7 +531,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { } let enum_ = discr.place().and_then(|discr| { - switch_on_enum_discriminant(self.tcx, &self.body, &self.body[block], discr) + switch_on_enum_discriminant(self.tcx, self.body, &self.body[block], discr) }); let Some((enum_place, enum_def)) = enum_ else { @@ -563,8 +554,6 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { // Mark all move paths that correspond to variants other than this one as maybe // uninitialized (in reality, they are *definitely* uninitialized). drop_flag_effects::on_all_inactive_variants( - self.tcx, - self.body, self.move_data(), enum_place, variant, @@ -589,7 +578,7 @@ impl<'a, 'tcx> AnalysisDomain<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> { fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) { state.0.clear(); - drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| { + drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| { assert!(s == DropFlagState::Present); state.0.insert(path); }); @@ -609,7 +598,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { _statement: &mir::Statement<'tcx>, location: Location, ) { - drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { Self::update_bits(trans, path, s) }) } @@ -620,7 +609,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { terminator: &'mir mir::Terminator<'tcx>, location: Location, ) -> TerminatorEdges<'mir, 'tcx> { - drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { Self::update_bits(trans, path, s) }); terminator.edges() @@ -628,7 +617,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { fn call_return_effect( &mut self, - trans: &mut impl GenKill<Self::Idx>, + trans: &mut Self::Domain, _block: mir::BasicBlock, return_places: CallReturnPlaces<'_, 'tcx>, ) { @@ -636,8 +625,6 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { // when a call returns successfully, that means we need to set // the bits for that dest_place to 1 (initialized). on_lookup_result_bits( - self.tcx, - self.body, self.move_data(), self.move_data().rev_lookup.find(place.as_ref()), |mpi| { @@ -725,7 +712,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { fn call_return_effect( &mut self, - trans: &mut impl GenKill<Self::Idx>, + trans: &mut Self::Domain, block: mir::BasicBlock, _return_places: CallReturnPlaces<'_, 'tcx>, ) { diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index bdfb6a6ff..04bae6ae2 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -23,7 +23,6 @@ use crate::{Analysis, AnalysisDomain, Backward, GenKill, GenKillAnalysis}; /// [`MaybeBorrowedLocals`]: super::MaybeBorrowedLocals /// [flow-test]: https://github.com/rust-lang/rust/blob/a08c47310c7d49cbdc5d7afb38408ba519967ecd/src/test/ui/mir-dataflow/liveness-ptr.rs /// [liveness]: https://en.wikipedia.org/wiki/Live_variable_analysis -#[derive(Clone, Copy)] pub struct MaybeLiveLocals; impl<'tcx> AnalysisDomain<'tcx> for MaybeLiveLocals { @@ -70,7 +69,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeLiveLocals { fn call_return_effect( &mut self, - trans: &mut impl GenKill<Self::Idx>, + trans: &mut Self::Domain, _block: mir::BasicBlock, return_places: CallReturnPlaces<'_, 'tcx>, ) { diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 5a58e3af8..646c70eb8 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -5,7 +5,7 @@ use rustc_middle::mir::*; use std::borrow::Cow; use super::MaybeBorrowedLocals; -use crate::{GenKill, ResultsClonedCursor}; +use crate::{GenKill, ResultsCursor}; #[derive(Clone)] pub struct MaybeStorageLive<'a> { @@ -18,12 +18,6 @@ impl<'a> MaybeStorageLive<'a> { } } -impl crate::CloneAnalysis for MaybeStorageLive<'_> { - fn clone_analysis(&self) -> Self { - self.clone() - } -} - impl<'tcx, 'a> crate::AnalysisDomain<'tcx> for MaybeStorageLive<'a> { type Domain = BitSet<Local>; @@ -78,7 +72,7 @@ impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> { fn call_return_effect( &mut self, - _trans: &mut impl GenKill<Self::Idx>, + _trans: &mut Self::Domain, _block: BasicBlock, _return_places: CallReturnPlaces<'_, 'tcx>, ) { @@ -150,7 +144,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead { fn call_return_effect( &mut self, - _trans: &mut impl GenKill<Self::Idx>, + _trans: &mut Self::Domain, _block: BasicBlock, _return_places: CallReturnPlaces<'_, 'tcx>, ) { @@ -158,28 +152,21 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead { } } -type BorrowedLocalsResults<'res, 'mir, 'tcx> = - ResultsClonedCursor<'res, 'mir, 'tcx, MaybeBorrowedLocals>; +type BorrowedLocalsResults<'mir, 'tcx> = ResultsCursor<'mir, 'tcx, MaybeBorrowedLocals>; /// Dataflow analysis that determines whether each local requires storage at a /// given location; i.e. whether its storage can go away without being observed. -pub struct MaybeRequiresStorage<'res, 'mir, 'tcx> { - borrowed_locals: BorrowedLocalsResults<'res, 'mir, 'tcx>, +pub struct MaybeRequiresStorage<'mir, 'tcx> { + borrowed_locals: BorrowedLocalsResults<'mir, 'tcx>, } -impl<'res, 'mir, 'tcx> MaybeRequiresStorage<'res, 'mir, 'tcx> { - pub fn new(borrowed_locals: BorrowedLocalsResults<'res, 'mir, 'tcx>) -> Self { +impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> { + pub fn new(borrowed_locals: BorrowedLocalsResults<'mir, 'tcx>) -> Self { MaybeRequiresStorage { borrowed_locals } } } -impl crate::CloneAnalysis for MaybeRequiresStorage<'_, '_, '_> { - fn clone_analysis(&self) -> Self { - Self { borrowed_locals: self.borrowed_locals.new_cursor() } - } -} - -impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> { +impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, 'tcx> { type Domain = BitSet<Local>; const NAME: &'static str = "requires_storage"; @@ -198,7 +185,7 @@ impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> { } } -impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> { +impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { type Idx = Local; fn domain_size(&self, body: &Body<'tcx>) -> usize { @@ -251,7 +238,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> { fn before_terminator_effect( &mut self, - trans: &mut impl GenKill<Self::Idx>, + trans: &mut Self::Domain, terminator: &Terminator<'tcx>, loc: Location, ) { @@ -347,7 +334,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> { fn call_return_effect( &mut self, - trans: &mut impl GenKill<Self::Idx>, + trans: &mut Self::Domain, _block: BasicBlock, return_places: CallReturnPlaces<'_, 'tcx>, ) { @@ -355,7 +342,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> { } } -impl<'tcx> MaybeRequiresStorage<'_, '_, 'tcx> { +impl<'tcx> MaybeRequiresStorage<'_, 'tcx> { /// Kill locals that are fully moved and have not been borrowed. fn check_for_move(&mut self, trans: &mut impl GenKill<Local>, loc: Location) { let body = self.borrowed_locals.body(); @@ -364,12 +351,12 @@ impl<'tcx> MaybeRequiresStorage<'_, '_, 'tcx> { } } -struct MoveVisitor<'a, 'res, 'mir, 'tcx, T> { - borrowed_locals: &'a mut BorrowedLocalsResults<'res, 'mir, 'tcx>, +struct MoveVisitor<'a, 'mir, 'tcx, T> { + borrowed_locals: &'a mut BorrowedLocalsResults<'mir, 'tcx>, trans: &'a mut T, } -impl<'tcx, T> Visitor<'tcx> for MoveVisitor<'_, '_, '_, 'tcx, T> +impl<'tcx, T> Visitor<'tcx> for MoveVisitor<'_, '_, 'tcx, T> where T: GenKill<Local>, { diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index eea0e030e..f0b21fd41 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -4,7 +4,7 @@ #![feature(let_chains)] #![feature(min_specialization)] #![feature(stmt_expr_attributes)] -#![feature(trusted_step)] +#![feature(try_blocks)] #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] @@ -14,24 +14,17 @@ extern crate tracing; #[macro_use] extern crate rustc_middle; -use rustc_ast::MetaItem; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; -use rustc_hir::def_id::DefId; -use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::symbol::{sym, Symbol}; +use rustc_middle::ty; pub use self::drop_flag_effects::{ drop_flag_effects_for_function_entry, drop_flag_effects_for_location, move_path_children_matching, on_all_children_bits, on_lookup_result_bits, }; pub use self::framework::{ - fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, AnalysisResults, Backward, - CloneAnalysis, Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, - MaybeReachable, Results, ResultsCloned, ResultsClonedCursor, ResultsCursor, ResultsRefCursor, - ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, + fmt, lattice, visit_results, Analysis, AnalysisDomain, Direction, GenKill, GenKillAnalysis, + JoinSemiLattice, MaybeReachable, Results, ResultsCursor, ResultsVisitable, ResultsVisitor, }; - +use self::framework::{Backward, SwitchIntEdgeEffects}; use self::move_paths::MoveData; pub mod debuginfo; @@ -46,26 +39,9 @@ pub mod storage; pub mod un_derefer; pub mod value_analysis; -fluent_messages! { "../messages.ftl" } - -pub(crate) mod indexes { - pub(crate) use super::move_paths::MovePathIndex; -} +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub struct MoveDataParamEnv<'tcx> { pub move_data: MoveData<'tcx>, pub param_env: ty::ParamEnv<'tcx>, } - -pub fn has_rustc_mir_with(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Option<MetaItem> { - for attr in tcx.get_attrs(def_id, sym::rustc_mir) { - let items = attr.meta_item_list(); - for item in items.iter().flat_map(|l| l.iter()) { - match item.meta_item() { - Some(mi) if mi.has_name(name) => return Some(mi.clone()), - _ => continue, - } - } - } - None -} diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs index 7ab1a9ed0..22cf39992 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs @@ -14,6 +14,7 @@ use self::abs_domain::{AbstractElem, Lift}; mod abs_domain; rustc_index::newtype_index! { + #[orderable] #[debug_format = "mp{}"] pub struct MovePathIndex {} } @@ -25,6 +26,7 @@ impl polonius_engine::Atom for MovePathIndex { } rustc_index::newtype_index! { + #[orderable] #[debug_format = "mo{}"] pub struct MoveOutIndex {} } diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index d3dce641b..448128b69 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -1,11 +1,3 @@ -use rustc_span::symbol::sym; -use rustc_span::Span; - -use rustc_index::bit_set::ChunkedBitSet; -use rustc_middle::mir::MirPass; -use rustc_middle::mir::{self, Body, Local, Location}; -use rustc_middle::ty::{self, Ty, TyCtxt}; - use crate::errors::{ PeekArgumentNotALocal, PeekArgumentUntracked, PeekBitNotSet, PeekMustBeNotTemporary, PeekMustBePlaceOrRefPlace, StopAfterDataFlowEndedCompilation, @@ -18,13 +10,33 @@ use crate::move_paths::{HasMoveData, MoveData}; use crate::move_paths::{LookupResult, MovePathIndex}; use crate::MoveDataParamEnv; use crate::{Analysis, JoinSemiLattice, ResultsCursor}; +use rustc_ast::MetaItem; +use rustc_hir::def_id::DefId; +use rustc_index::bit_set::ChunkedBitSet; +use rustc_middle::mir::MirPass; +use rustc_middle::mir::{self, Body, Local, Location}; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::symbol::{sym, Symbol}; +use rustc_span::Span; pub struct SanityCheck; +fn has_rustc_mir_with(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Option<MetaItem> { + for attr in tcx.get_attrs(def_id, sym::rustc_mir) { + let items = attr.meta_item_list(); + for item in items.iter().flat_map(|l| l.iter()) { + match item.meta_item() { + Some(mi) if mi.has_name(name) => return Some(mi.clone()), + _ => continue, + } + } + } + None +} + // FIXME: This should be a `MirLint`, but it needs to be moved back to `rustc_mir_transform` first. impl<'tcx> MirPass<'tcx> for SanityCheck { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - use crate::has_rustc_mir_with; let def_id = body.source.def_id(); if !tcx.has_attr(def_id, sym::rustc_mir) { debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); @@ -34,7 +46,7 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { } let param_env = tcx.param_env(def_id); - let move_data = MoveData::gather_moves(&body, tcx, param_env, |_| true); + let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true); let mdpe = MoveDataParamEnv { move_data, param_env }; if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() { @@ -54,7 +66,7 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { } if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_definite_init).is_some() { - let flow_def_inits = DefinitelyInitializedPlaces::new(tcx, body, &mdpe) + let flow_def_inits = DefinitelyInitializedPlaces::new(body, &mdpe) .into_engine(tcx, body) .iterate_to_fixpoint(); @@ -89,10 +101,8 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { /// (If there are any calls to `rustc_peek` that do not match the /// expression form above, then that emits an error as well, but those /// errors are not intended to be used for unit tests.) -pub fn sanity_check_via_rustc_peek<'tcx, A>( - tcx: TyCtxt<'tcx>, - mut cursor: ResultsCursor<'_, 'tcx, A>, -) where +fn sanity_check_via_rustc_peek<'tcx, A>(tcx: TyCtxt<'tcx>, mut cursor: ResultsCursor<'_, 'tcx, A>) +where A: RustcPeekAt<'tcx>, { let def_id = cursor.body().source.def_id(); @@ -129,7 +139,8 @@ pub fn sanity_check_via_rustc_peek<'tcx, A>( ) => { let loc = Location { block: bb, statement_index }; cursor.seek_before_primary_effect(loc); - let (state, analysis) = cursor.get_with_analysis(); + let state = cursor.get(); + let analysis = cursor.analysis(); analysis.peek_at(tcx, *place, state, call); } @@ -173,7 +184,7 @@ impl PeekCallKind { } #[derive(Clone, Copy, Debug)] -pub struct PeekCall { +struct PeekCall { arg: Local, kind: PeekCallKind, span: Span, @@ -221,7 +232,7 @@ impl PeekCall { } } -pub trait RustcPeekAt<'tcx>: Analysis<'tcx> { +trait RustcPeekAt<'tcx>: Analysis<'tcx> { fn peek_at( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_mir_dataflow/src/un_derefer.rs b/compiler/rustc_mir_dataflow/src/un_derefer.rs index 874d50ffd..b803ecc57 100644 --- a/compiler/rustc_mir_dataflow/src/un_derefer.rs +++ b/compiler/rustc_mir_dataflow/src/un_derefer.rs @@ -3,13 +3,13 @@ use rustc_middle::mir::*; /// Used for reverting changes made by `DerefSeparator` #[derive(Default, Debug)] -pub struct UnDerefer<'tcx> { +pub(crate) struct UnDerefer<'tcx> { deref_chains: FxHashMap<Local, Vec<PlaceRef<'tcx>>>, } impl<'tcx> UnDerefer<'tcx> { #[inline] - pub fn insert(&mut self, local: Local, reffed: PlaceRef<'tcx>) { + pub(crate) fn insert(&mut self, local: Local, reffed: PlaceRef<'tcx>) { let mut chain = self.deref_chains.remove(&reffed.local).unwrap_or_default(); chain.push(reffed); self.deref_chains.insert(local, chain); @@ -17,7 +17,7 @@ impl<'tcx> UnDerefer<'tcx> { /// Returns the chain of places behind `DerefTemp` locals #[inline] - pub fn deref_chain(&self, local: Local) -> &[PlaceRef<'tcx>] { + pub(crate) fn deref_chain(&self, local: Local) -> &[PlaceRef<'tcx>] { self.deref_chains.get(&local).map(Vec::as_slice).unwrap_or_default() } @@ -25,7 +25,7 @@ impl<'tcx> UnDerefer<'tcx> { /// /// See [`PlaceRef::iter_projections`] #[inline] - pub fn iter_projections( + pub(crate) fn iter_projections( &self, place: PlaceRef<'tcx>, ) -> impl Iterator<Item = (PlaceRef<'tcx>, PlaceElem<'tcx>)> + '_ { diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 025d2ddfd..2802f5491 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -332,8 +332,6 @@ pub struct ValueAnalysisWrapper<T>(pub T); impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper<T> { type Domain = State<T::Value>; - type Direction = crate::Forward; - const NAME: &'static str = T::NAME; fn bottom_value(&self, _body: &Body<'tcx>) -> Self::Domain { @@ -476,26 +474,10 @@ impl<V: Clone> State<V> { } } - pub fn is_reachable(&self) -> bool { + fn is_reachable(&self) -> bool { matches!(&self.0, StateData::Reachable(_)) } - pub fn mark_unreachable(&mut self) { - self.0 = StateData::Unreachable; - } - - pub fn flood_all(&mut self) - where - V: HasTop, - { - self.flood_all_with(V::TOP) - } - - pub fn flood_all_with(&mut self, value: V) { - let StateData::Reachable(values) = &mut self.0 else { return }; - values.raw.fill(value); - } - /// Assign `value` to all places that are contained in `place` or may alias one. pub fn flood_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) { self.flood_with_tail_elem(place, None, map, value) @@ -510,7 +492,7 @@ impl<V: Clone> State<V> { } /// Assign `value` to the discriminant of `place` and all places that may alias it. - pub fn flood_discr_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) { + fn flood_discr_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) { self.flood_with_tail_elem(place, Some(TrackElem::Discriminant), map, value) } @@ -546,7 +528,7 @@ impl<V: Clone> State<V> { /// This does nothing if the place is not tracked. /// /// The target place must have been flooded before calling this method. - pub fn insert_idx(&mut self, target: PlaceIndex, result: ValueOrPlace<V>, map: &Map) { + fn insert_idx(&mut self, target: PlaceIndex, result: ValueOrPlace<V>, map: &Map) { match result { ValueOrPlace::Value(value) => self.insert_value_idx(target, value, map), ValueOrPlace::Place(source) => self.insert_place_idx(target, source, map), @@ -841,7 +823,7 @@ impl Map { ) { // Allocate a value slot if it doesn't have one, and the user requested one. assert!(self.places[place].value_index.is_none()); - if tcx.layout_of(param_env.and(ty)).map_or(false, |layout| layout.abi.is_scalar()) { + if tcx.layout_of(param_env.and(ty)).is_ok_and(|layout| layout.abi.is_scalar()) { self.places[place].value_index = Some(self.value_count.into()); self.value_count += 1; } @@ -910,18 +892,13 @@ impl Map { self.inner_values[root] = start..end; } - /// Returns the number of tracked places, i.e., those for which a value can be stored. - pub fn tracked_places(&self) -> usize { - self.value_count - } - /// Applies a single projection element, yielding the corresponding child. pub fn apply(&self, place: PlaceIndex, elem: TrackElem) -> Option<PlaceIndex> { self.projections.get(&(place, elem)).copied() } /// Locates the given place, if it exists in the tree. - pub fn find_extra( + fn find_extra( &self, place: PlaceRef<'_>, extra: impl IntoIterator<Item = TrackElem>, @@ -954,7 +931,7 @@ impl Map { } /// Iterate over all direct children. - pub fn children(&self, parent: PlaceIndex) -> impl Iterator<Item = PlaceIndex> + '_ { + fn children(&self, parent: PlaceIndex) -> impl Iterator<Item = PlaceIndex> + '_ { Children::new(self, parent) } @@ -979,11 +956,7 @@ impl Map { // The local is not tracked at all, so it does not alias anything. return; }; - let elems = place - .projection - .iter() - .map(|&elem| elem.try_into()) - .chain(tail_elem.map(Ok).into_iter()); + let elems = place.projection.iter().map(|&elem| elem.try_into()).chain(tail_elem.map(Ok)); for elem in elems { // A field aliases the parent place. if let Some(vi) = self.places[index].value_index { |