From d37ed10634131dd678697609f9060aaba8bacd41 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <n.nethercote@gmail.com>
Date: Fri, 29 Nov 2024 07:00:42 +1100
Subject: [PATCH 1/3] Fix crash with `-Zdump-mir-dataflow`

As of #133155 `Formatter:new` uses `as_results_cursor` to create a
non-mutable results reference, and then later that is accessed via
`deref_mut` which results in a runtime abort. Changing to
`as_results_cursor_mut` fixes it.

Fixes #133641.
---
 compiler/rustc_mir_dataflow/src/framework/graphviz.rs | 4 ++--
 compiler/rustc_mir_dataflow/src/framework/mod.rs      | 4 ++--
 compiler/rustc_mir_dataflow/src/framework/results.rs  | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index 6e4994af8b4..ecb1ab7f2ba 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -47,11 +47,11 @@ where
 {
     pub(crate) fn new(
         body: &'mir Body<'tcx>,
-        results: &'mir Results<'tcx, A>,
+        results: &'mir mut Results<'tcx, A>,
         style: OutputStyle,
     ) -> Self {
         let reachable = mir::traversal::reachable_as_bitset(body);
-        Formatter { cursor: results.as_results_cursor(body).into(), style, reachable }
+        Formatter { cursor: results.as_results_cursor_mut(body).into(), style, reachable }
     }
 
     fn body(&self) -> &'mir Body<'tcx> {
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index f1ea94e1689..b9407882ec5 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -281,10 +281,10 @@ pub trait Analysis<'tcx> {
             );
         }
 
-        let results = Results { analysis: self, entry_sets };
+        let mut results = Results { analysis: self, entry_sets };
 
         if tcx.sess.opts.unstable_opts.dump_mir_dataflow {
-            let res = write_graphviz_results(tcx, body, &results, pass_name);
+            let res = write_graphviz_results(tcx, body, &mut results, pass_name);
             if let Err(e) = res {
                 error!("Failed to write graphviz dataflow results: {}", e);
             }
diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs
index 8493a7aa44b..72e9d4dba57 100644
--- a/compiler/rustc_mir_dataflow/src/framework/results.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/results.rs
@@ -95,7 +95,7 @@ where
 pub(super) fn write_graphviz_results<'tcx, A>(
     tcx: TyCtxt<'tcx>,
     body: &mir::Body<'tcx>,
-    results: &Results<'tcx, A>,
+    results: &mut Results<'tcx, A>,
     pass_name: Option<&'static str>,
 ) -> std::io::Result<()>
 where

From 9f2f6906ffe05d63488f717694bdb9e8d2fb8815 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <n.nethercote@gmail.com>
Date: Mon, 2 Dec 2024 10:50:06 +1100
Subject: [PATCH 2/3] Add test for `-Zdump-mir-dataflow`.

---
 tests/mir-opt/dataflow.main.maybe_init.borrowck.dot | 6 ++++++
 tests/mir-opt/dataflow.rs                           | 6 ++++++
 2 files changed, 12 insertions(+)
 create mode 100644 tests/mir-opt/dataflow.main.maybe_init.borrowck.dot
 create mode 100644 tests/mir-opt/dataflow.rs

diff --git a/tests/mir-opt/dataflow.main.maybe_init.borrowck.dot b/tests/mir-opt/dataflow.main.maybe_init.borrowck.dot
new file mode 100644
index 00000000000..7c7d8921fb3
--- /dev/null
+++ b/tests/mir-opt/dataflow.main.maybe_init.borrowck.dot
@@ -0,0 +1,6 @@
+digraph graph_for_def_id_0_3 {
+    graph[fontname="Courier, monospace"];
+    node[fontname="Courier, monospace"];
+    edge[fontname="Courier, monospace"];
+    bb_0[label=<<table border="1" cellborder="1" cellspacing="0" cellpadding="3" sides="rb"><tr><td colspan="3" sides="tl">bb0</td></tr><tr><td colspan="2" bgcolor="#a0a0a0" sides="tl">MIR</td><td bgcolor="#a0a0a0" sides="tl">STATE</td></tr><tr><td valign="bottom" sides="tl"  align="right"></td><td valign="bottom" sides="tl"  align="left">(on start)</td><td colspan="1" valign="bottom" sides="tl"  align="left">{}</td></tr><tr><td valign="top" sides="tl" bgcolor="#f0f0f0" align="right">0</td><td valign="top" sides="tl" bgcolor="#f0f0f0" align="left">_0 = const ()</td><td valign="top" sides="tl" bgcolor="#f0f0f0" align="left"><font color="darkgreen">+_0</font></td></tr><tr><td valign="top" sides="tl"  align="right">T</td><td valign="top" sides="tl"  align="left">return</td><td valign="top" sides="tl"  align="left"></td></tr><tr><td valign="bottom" sides="tl" bgcolor="#f0f0f0" align="right"></td><td valign="bottom" sides="tl" bgcolor="#f0f0f0" align="left">(on end)</td><td colspan="1" valign="bottom" sides="tl" bgcolor="#f0f0f0" align="left">{_0}</td></tr></table>>][shape="none"];
+}
diff --git a/tests/mir-opt/dataflow.rs b/tests/mir-opt/dataflow.rs
new file mode 100644
index 00000000000..3a28f5d47b9
--- /dev/null
+++ b/tests/mir-opt/dataflow.rs
@@ -0,0 +1,6 @@
+// skip-filecheck
+// Test graphviz dataflow output
+//@ compile-flags: -Z dump-mir=main -Z dump-mir-dataflow
+
+// EMIT_MIR dataflow.main.maybe_init.borrowck.dot
+fn main() {}

From cecef131a259320efb0a7d693ef4c594a3d93241 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <n.nethercote@gmail.com>
Date: Mon, 2 Dec 2024 10:58:27 +1100
Subject: [PATCH 3/3] Simplify `ResultsHandle`.

The `Borrowed` variant is no longer used. This commit removes it, along
with the `as_results_cursor` method that produces it, and renames
`as_results_cursor_mut` as `as_results_cursor`.
---
 compiler/rustc_mir_dataflow/src/framework/cursor.rs |  5 -----
 .../rustc_mir_dataflow/src/framework/graphviz.rs    |  2 +-
 .../rustc_mir_dataflow/src/framework/results.rs     | 13 ++-----------
 compiler/rustc_mir_transform/src/coroutine.rs       |  2 +-
 4 files changed, 4 insertions(+), 18 deletions(-)

diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
index 11cf8c3e898..4a9bcdaddb3 100644
--- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
@@ -15,7 +15,6 @@ pub enum ResultsHandle<'a, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
-    Borrowed(&'a Results<'tcx, A>),
     BorrowedMut(&'a mut Results<'tcx, A>),
     Owned(Results<'tcx, A>),
 }
@@ -28,7 +27,6 @@ where
 
     fn deref(&self) -> &Results<'tcx, A> {
         match self {
-            ResultsHandle::Borrowed(borrowed) => borrowed,
             ResultsHandle::BorrowedMut(borrowed) => borrowed,
             ResultsHandle::Owned(owned) => owned,
         }
@@ -41,9 +39,6 @@ where
 {
     fn deref_mut(&mut self) -> &mut Results<'tcx, A> {
         match self {
-            ResultsHandle::Borrowed(_borrowed) => {
-                panic!("tried to deref_mut a `ResultsHandle::Borrowed")
-            }
             ResultsHandle::BorrowedMut(borrowed) => borrowed,
             ResultsHandle::Owned(owned) => owned,
         }
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index ecb1ab7f2ba..561229cf725 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -51,7 +51,7 @@ where
         style: OutputStyle,
     ) -> Self {
         let reachable = mir::traversal::reachable_as_bitset(body);
-        Formatter { cursor: results.as_results_cursor_mut(body).into(), style, reachable }
+        Formatter { cursor: results.as_results_cursor(body).into(), style, reachable }
     }
 
     fn body(&self) -> &'mir Body<'tcx> {
diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs
index 72e9d4dba57..c4321c454e6 100644
--- a/compiler/rustc_mir_dataflow/src/framework/results.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/results.rs
@@ -37,18 +37,9 @@ impl<'tcx, A> Results<'tcx, A>
 where
     A: Analysis<'tcx>,
 {
-    /// Creates a `ResultsCursor` that can inspect these `Results`. Immutably borrows the `Results`,
-    /// which is appropriate when the `Results` is used outside the cursor.
+    /// Creates a `ResultsCursor` that mutably borrows the `Results`, which is appropriate when the
+    /// `Results` is also used outside the cursor.
     pub fn as_results_cursor<'mir>(
-        &'mir self,
-        body: &'mir mir::Body<'tcx>,
-    ) -> ResultsCursor<'mir, 'tcx, A> {
-        ResultsCursor::new(body, ResultsHandle::Borrowed(self))
-    }
-
-    /// Creates a `ResultsCursor` that can mutate these `Results`. Mutably borrows the `Results`,
-    /// which is appropriate when the `Results` is used outside the cursor.
-    pub fn as_results_cursor_mut<'mir>(
         &'mir mut self,
         body: &'mir mir::Body<'tcx>,
     ) -> ResultsCursor<'mir, 'tcx, A> {
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 9b9aeccf890..858752a3f01 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -680,7 +680,7 @@ fn locals_live_across_suspend_points<'tcx>(
     let mut requires_storage_results =
         MaybeRequiresStorage::new(borrowed_locals_results.into_results_cursor(body))
             .iterate_to_fixpoint(tcx, body, None);
-    let mut requires_storage_cursor = requires_storage_results.as_results_cursor_mut(body);
+    let mut requires_storage_cursor = requires_storage_results.as_results_cursor(body);
 
     // Calculate the liveness of MIR locals ignoring borrows.
     let mut liveness =