about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2023-11-23 18:19:43 +1100
committerNicholas Nethercote <n.nethercote@gmail.com>2023-11-27 10:35:43 +1100
commitcf82b410f91082bce79bb70d5d94633f946a3b77 (patch)
tree5b8ac9d8417e18ad18fbd1993b0b99db71230f2d
parent3dea72aa1bf0ed5e5ccd36e8ee6c1c97976e5d25 (diff)
downloadrust-cf82b410f91082bce79bb70d5d94633f946a3b77.tar.gz
rust-cf82b410f91082bce79bb70d5d94633f946a3b77.zip
Remove another use of `as_results_cursor`.
The new code is a little clunky, but I couldn't see how to make it
better.
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/engine.rs56
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs45
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs1
3 files changed, 62 insertions, 40 deletions
diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs
index 442b1facfc6..90fc91d0123 100644
--- a/compiler/rustc_mir_dataflow/src/framework/engine.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs
@@ -271,29 +271,31 @@ where
             );
         }
 
-        let mut results = Results { analysis, entry_sets, _marker: PhantomData };
+        let results = Results { analysis, entry_sets, _marker: PhantomData };
 
         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>,
@@ -304,23 +306,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 {
@@ -336,11 +345,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 832d1cba9a7..fa16cac3168 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -12,7 +12,7 @@ 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(crate) enum OutputStyle {
@@ -29,27 +29,31 @@ impl OutputStyle {
     }
 }
 
-pub(crate) 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(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()
     }
 }
 
@@ -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>,
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index abe9dd45ea1..accc13bf94d 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -4,6 +4,7 @@
 #![feature(let_chains)]
 #![feature(min_specialization)]
 #![feature(stmt_expr_attributes)]
+#![feature(try_blocks)]
 #![recursion_limit = "256"]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]