about summary refs log tree commit diff
path: root/compiler/rustc_mir_dataflow/src/framework
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2024-10-30 08:45:46 +1100
committerNicholas Nethercote <n.nethercote@gmail.com>2024-10-30 09:41:46 +1100
commite54c177118a5150b819c8a84054504ab8e1e7748 (patch)
tree6741e0ee2a2b3051016b8cc10adfdbec04c9afe3 /compiler/rustc_mir_dataflow/src/framework
parent31e102c509192189be841954f38962eb3cd9e2e2 (diff)
Remove `Analysis::into_engine`.
This is a standard pattern:
```
MyAnalysis.into_engine(tcx, body).iterate_to_fixpoint()
```
`into_engine` and `iterate_to_fixpoint` are always called in pairs, but
sometimes with a builder-style `pass_name` call between them. But a
builder-style interface is overkill here. This has been bugging me a for
a while.

This commit:
- Merges `Engine::new` and `Engine::iterate_to_fixpoint`. This removes
  the need for `Engine` to have fields, leaving it as a trivial type
  that the next commit will remove.
- Renames `Analysis::into_engine` as `Analysis::iterate_to_fixpoint`,
  gives it an extra argument for the optional pass name, and makes it
  call `Engine::iterate_to_fixpoint` instead of `Engine::new`.

This turns the pattern from above into this:
```
MyAnalysis.iterate_to_fixpoint(tcx, body, None)
```
which is shorter at every call site, and there's less plumbing required
to support it.
Diffstat (limited to 'compiler/rustc_mir_dataflow/src/framework')
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/engine.rs47
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/mod.rs33
2 files changed, 31 insertions, 49 deletions
diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs
index cbd1083d037..44fda84ce03 100644
--- a/compiler/rustc_mir_dataflow/src/framework/engine.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs
@@ -71,25 +71,21 @@ where
 }
 
 /// A solver for dataflow problems.
-pub struct Engine<'mir, 'tcx, A>
-where
-    A: Analysis<'tcx>,
-{
-    tcx: TyCtxt<'tcx>,
-    body: &'mir mir::Body<'tcx>,
-    entry_sets: IndexVec<BasicBlock, A::Domain>,
-    pass_name: Option<&'static str>,
-    analysis: A,
-}
+pub struct Engine;
 
-impl<'mir, 'tcx, A, D> Engine<'mir, 'tcx, A>
-where
-    A: Analysis<'tcx, Domain = D>,
-    D: Clone + JoinSemiLattice,
-{
+impl Engine {
     /// Creates a new `Engine` to solve a dataflow problem with an arbitrary transfer
     /// function.
-    pub(crate) fn new(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, analysis: A) -> Self {
+    pub(crate) fn iterate_to_fixpoint<'mir, 'tcx, A>(
+        tcx: TyCtxt<'tcx>,
+        body: &'mir mir::Body<'tcx>,
+        mut analysis: A,
+        pass_name: Option<&'static str>,
+    ) -> Results<'tcx, A>
+    where
+        A: Analysis<'tcx>,
+        A::Domain: DebugWithContext<A> + Clone + JoinSemiLattice,
+    {
         let mut entry_sets =
             IndexVec::from_fn_n(|_| analysis.bottom_value(body), body.basic_blocks.len());
         analysis.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]);
@@ -99,25 +95,6 @@ where
             bug!("`initialize_start_block` is not yet supported for backward dataflow analyses");
         }
 
-        Engine { analysis, tcx, body, pass_name: None, entry_sets }
-    }
-
-    /// Adds an identifier to the graphviz output for this particular run of a dataflow analysis.
-    ///
-    /// Some analyses are run multiple times in the compilation pipeline. Give them a `pass_name`
-    /// to differentiate them. Otherwise, only the results for the latest run will be saved.
-    pub fn pass_name(mut self, name: &'static str) -> Self {
-        self.pass_name = Some(name);
-        self
-    }
-
-    /// Computes the fixpoint for this dataflow problem and returns it.
-    pub fn iterate_to_fixpoint(self) -> Results<'tcx, A>
-    where
-        A::Domain: DebugWithContext<A>,
-    {
-        let Engine { mut analysis, body, mut entry_sets, tcx, pass_name } = self;
-
         let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks.len());
 
         if A::Direction::IS_FORWARD {
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index 959f1ea5340..5ad05921b4f 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -7,18 +7,17 @@
 //!
 //! The `impls` module contains several examples of dataflow analyses.
 //!
-//! Create an `Engine` for your analysis using the `into_engine` method on the `Analysis` trait,
-//! then call `iterate_to_fixpoint`. From there, you can use a `ResultsCursor` to inspect the
-//! fixpoint solution to your dataflow problem, or implement the `ResultsVisitor` interface and use
-//! `visit_results`. The following example uses the `ResultsCursor` approach.
+//! Then call `iterate_to_fixpoint` on your type that impls `Analysis` to get a `Results`. From
+//! there, you can use a `ResultsCursor` to inspect the fixpoint solution to your dataflow problem,
+//! or implement the `ResultsVisitor` interface and use `visit_results`. The following example uses
+//! the `ResultsCursor` approach.
 //!
 //! ```ignore (cross-crate-imports)
-//! use rustc_const_eval::dataflow::Analysis; // Makes `into_engine` available.
+//! use rustc_const_eval::dataflow::Analysis; // Makes `iterate_to_fixpoint` available.
 //!
 //! fn do_my_analysis(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) {
 //!     let analysis = MyAnalysis::new()
-//!         .into_engine(tcx, body)
-//!         .iterate_to_fixpoint()
+//!         .iterate_to_fixpoint(tcx, body, None)
 //!         .into_results_cursor(body);
 //!
 //!     // Print the dataflow state *after* each statement in the start block.
@@ -39,6 +38,8 @@ use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet};
 use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges};
 use rustc_middle::ty::TyCtxt;
 
+use super::fmt::DebugWithContext;
+
 mod cursor;
 mod direction;
 mod engine;
@@ -223,26 +224,30 @@ pub trait Analysis<'tcx> {
 
     /* Extension methods */
 
-    /// Creates an `Engine` to find the fixpoint for this dataflow problem.
+    /// Finds the fixpoint for this dataflow problem.
     ///
     /// You shouldn't need to override this. Its purpose is to enable method chaining like so:
     ///
     /// ```ignore (cross-crate-imports)
     /// let results = MyAnalysis::new(tcx, body)
-    ///     .into_engine(tcx, body, def_id)
-    ///     .iterate_to_fixpoint()
+    ///     .iterate_to_fixpoint(tcx, body, None)
     ///     .into_results_cursor(body);
     /// ```
-    #[inline]
-    fn into_engine<'mir>(
+    /// You can optionally add a `pass_name` to the graphviz output for this particular run of a
+    /// dataflow analysis. Some analyses are run multiple times in the compilation pipeline.
+    /// Without a `pass_name` to differentiates them, only the results for the latest run will be
+    /// saved.
+    fn iterate_to_fixpoint<'mir>(
         self,
         tcx: TyCtxt<'tcx>,
         body: &'mir mir::Body<'tcx>,
-    ) -> Engine<'mir, 'tcx, Self>
+        pass_name: Option<&'static str>,
+    ) -> Results<'tcx, Self>
     where
         Self: Sized,
+        Self::Domain: DebugWithContext<Self>,
     {
-        Engine::new(tcx, body, self)
+        Engine::iterate_to_fixpoint(tcx, body, self, pass_name)
     }
 }